本文簡要介紹ruby語言中 Gem::Security模塊
的用法。
簽署 gems
Gem::Security
為 gem 實現加密簽名。以下部分是step-by-step 指南,用於使用已簽名的 gem 並生成您自己的。
演練
建立你的證書
為了開始簽署您的 gem,您需要構建一個私鑰和一個 self-signed 證書。就是這樣:
# build a private key and certificate for yourself: $ gem cert --build you@example.com
這可能需要幾秒鍾到一兩分鍾,具體取決於計算機的速度(公鑰算法並不是世界上最快的加密算法)。完成後,您將在當前目錄中看到文件 “gem-private_key.pem” 和 “gem-public_cert.pem”。
首先要做的事情:如果您在該目錄中還沒有 key 和證書,請將這兩個文件移動到 ~/.gem。確保文件權限使其他人無法讀取 key (默認情況下文件被安全保存)。
隱藏您的私鑰;如果它被泄露,有人可以像你一樣簽署包(注意:PKI 有降低被盜 key 風險的方法;稍後會詳細介紹)。
簽名 gems
在 RubyGems 2 和更新版本中,無需額外工作即可簽署 gem。 RubyGems 將自動在您的主目錄中找到您的 key 和證書,並使用它們來簽署新打包的 gem。
如果您的證書不是self-signed(由第三方簽名),RubyGems 將嘗試從受信任的證書加載證書鏈。使用 gem cert --add signing_cert.pem
將您的簽名者添加為受信任的證書。有關證書鏈的更多信息,請參見下文。
如果您構建您的 gem,它將自動被簽名。如果您查看您的 gem 文件,您會看到添加了幾個新文件:
$ tar tf your-gem-1.0.gem metadata.gz metadata.gz.sig # metadata signature data.tar.gz data.tar.gz.sig # data signature checksums.yaml.gz checksums.yaml.gz.sig # checksums signature
手動簽名 gem
如果您希望將 key 存儲在單獨的安全位置,則需要設置您的 gem 以進行手動簽名。為此,請在打包 gem 之前在 gemspec 中設置 signing_key
和 cert_chain
:
s.signing_key = '/secure/path/to/gem-private_key.pem'
s.cert_chain = %w[/secure/path/to/gem-public_cert.pem]
當您使用這些選項集打包 gem 時,RubyGems 將自動從安全路徑加載您的 key 和證書。
簽名的 gem 和安全策略
現在讓我們驗證簽名。繼續安裝 gem,但添加以下選項:-P HighSecurity
,如下所示:
# install the gem with using the security policy "HighSecurity" $ sudo gem install your.gem -P HighSecurity
-P
選項設置您的安全策略 - 我們將在稍後討論。誒,這是什麽?
$ gem install -P HighSecurity your-gem-1.0.gem ERROR: While executing gem ... (Gem::Security::Exception) root cert /CN=you/DC=example is not trusted
這裏的罪魁禍首是安全策略。 RubyGems 有幾種不同的安全策略。讓我們休息一下,看看安全策略。以下是可用安全策略的列表,以及每個安全策略的簡要說明:
-
NoSecurity
- 好吧,根本沒有安全保障。簽名包被視為未簽名包。 -
LowSecurity
- 幾乎沒有安全保障。如果一個包被簽名,那麽 RubyGems 將確保簽名與簽名證書匹配,並且簽名證書沒有過期,但就是這樣。惡意用戶可以輕鬆繞過這種安全措施。 -
MediumSecurity
- 比LowSecurity
和NoSecurity
好,但仍然容易出錯。包內容根據簽名證書進行驗證,並檢查簽名證書的有效性,並檢查證書鏈的其餘部分(如果您不知道證書鏈是什麽,請繼續關注,我們會解決的) .LowSecurity
最大的改進是MediumSecurity
不會安裝由不受信任的來源簽名的包。不幸的是,MediumSecurity
仍然不是完全安全的——惡意用戶仍然可以解壓 gem、剝離簽名並分發未簽名的 gem。 -
HighSecurity
- 這是讓我們陷入困境的蟲子。HighSecurity
策略與MediumSecurity
策略相同,隻是它不允許未簽名的 gem。惡意用戶在這裏沒有很多選擇;他們不能在不使簽名失效的情況下修改包內容,也不能修改或刪除簽名或簽名證書鏈,或者RubyGems將簡單地拒絕安裝包。哦,好吧,也許他們會給 CPAN 用戶帶來更好的運氣 :)。
RubyGems 拒絕安裝閃亮的新簽名 gem 的原因是它來自不受信任的來源。好吧,您的代碼是可靠的(自然),因此您需要將自己添加為受信任的來源:
# add trusted certificate gem cert --add ~/.gem/gem-public_cert.pem
您現在已將公共證書添加為可信來源。現在,您可以輕鬆安裝由您的私鑰簽名的軟件包。讓我們再次嘗試上麵的安裝命令:
# install the gem with using the HighSecurity policy (and this time # without any shenanigans) $ gem install -P HighSecurity your-gem-1.0.gem Successfully installed your-gem-1.0 1 gem installed
這次RubyGems 將接受您簽名的包並開始安裝。
在等待 RubyGems 運行時,它很神奇,通過運行 gem help cert
查看其他一些安全命令:
Options: -a, --add CERT Add a trusted certificate. -l, --list [FILTER] List trusted certificates where the subject contains FILTER -r, --remove FILTER Remove trusted certificates where the subject contains FILTER -b, --build EMAIL_ADDR Build private key and self-signed certificate for EMAIL_ADDR -C, --certificate CERT Signing certificate for --sign -K, --private-key KEY Key for --sign or --build -A, --key-algorithm ALGORITHM Select key algorithm for --build from RSA, DSA, or EC. Defaults to RSA. -s, --sign CERT Signs CERT with the key from -K and the certificate from -C -d, --days NUMBER_OF_DAYS Days before the certificate expires -R, --re-sign Re-signs the certificate from -C with the key from -K
我們已經介紹了 --build
選項,而 --add
、 --list
和 --remove
命令看起來相當簡單;它們允許您添加、列出和刪除受信任證書列表中的證書。但是這個 --sign
選項有什麽用呢?
證書鏈
為了回答這個問題,讓我們看一下我之前提到的概念“certificate chains”。 self-signed 證書有幾個問題:首先,self-signed 證書不能提供很多安全性。當然,證書上寫著 Yukihiro Matsumoto,但我怎麽知道它實際上是由 matz 自己生成和簽名的,除非他親自給我證書?
第二個問題是可擴展性。當然,如果有 50 個 gem 作者,那麽我就有 50 個受信任的證書,沒問題。如果有 500 位 gem 作者怎麽辦? 1000?不得不不斷地添加新的受信任證書是一件痛苦的事情,而且它實際上通過鼓勵RubyGems 用戶盲目信任新證書而降低了信任係統的安全性。
這就是證書鏈的用武之地。證書鏈在頒發證書和子證書之間建立了任意長的信任鏈。因此,我們不是在per-developer 基礎上信任證書,而是使用證書鏈的 PKI 概念來構建信任的邏輯層次結構。這是基於(大致)地理的信任層次結構的假設示例:
-------------------------- | rubygems@rubygems.org | -------------------------- | ----------------------------------- | | ---------------------------- ----------------------------- | seattlerb@seattlerb.org | | dcrubyists@richkilmer.com | ---------------------------- ----------------------------- | | | | --------------- ---------------- ----------- -------------- | drbrain | | zenspider | | pabs@dc | | tomcope@dc | --------------- ---------------- ----------- --------------
現在,用戶無需擁有 4 個受信任的證書(一個用於 drbrain、zenspider、pabs@dc 和 tomecope@dc),而實際上可以使用一個證書,即 “rubygems@rubygems.org” 證書。
這是它的工作原理:
我安裝了“rdoc-3.12.gem”,這是一個由“drbrain” 簽名的包。我從未聽說過“drbrain”,但他的證書具有來自“seattle.rb@seattlerb.org” 證書的有效簽名,而後者又具有來自“rubygems@rubygems.org” 證書的有效簽名。瞧!在這一點上,我相信由“drbrain” 簽名的包更合理,因為我可以建立到我確實信任的“rubygems@rubygems.org” 的鏈。
簽署證書
--sign
選項允許這一切發生。開發人員使用 --build
選項創建他們的構建證書,然後通過將其帶到他們的下一個區域 Ruby 聚會(在我們的假設示例中)來簽署他們的證書,並由持有區域 RubyGems 簽名的人在那裏簽名證書,由頂級 RubyGems 證書的持有者在下一個 RubyConf 簽名。在每一點,發行者運行相同的命令:
# sign a certificate with the specified key and certificate # (note that this modifies client_cert.pem!) $ gem cert -K /mnt/floppy/issuer-priv_key.pem -C issuer-pub_cert.pem --sign client_cert.pem
然後頒發證書的持有者(在這種情況下,您的好友“drbrain”)可以開始使用此簽名證書來簽署 RubyGems。順便說一句,為了讓其他人知道他的新簽名證書,“drbrain”會將他新簽名的證書保存為~/.gem/gem-public_cert.pem
顯然,這個RubyGems 信任基礎設施還不存在。此外,在“real world” 中,頒發者實際上是根據證書請求生成子證書,而不是簽署現有證書。我們假設的基礎設施缺少證書撤銷係統。這些是將來可以修複的……
在這一點上,您應該知道如何做所有這些新的和有趣的事情:
-
構建 gem 簽名 key 和證書
-
調整您的安全策略
-
修改您的信任證書列表
-
簽署證書
手動驗證簽名
如果您不信任RubyGems,您可以手動驗證 gem 簽名:
-
獲取並解壓 gem
gem fetch some_signed_gem tar -xf some_signed_gem-1.0.gem
-
從 gemspec 中獲取公鑰
gem spec some_signed_gem-1.0.gem cert_chain | \ ruby -rpsych -e 'puts Psych.load($stdin)' > public_key.crt
-
生成 data.tar.gz 的 SHA1 哈希
openssl dgst -sha1 < data.tar.gz > my.hash
-
驗證簽名
openssl rsautl -verify -inkey public_key.crt -certin \ -in data.tar.gz.sig > verified.hash
-
將您的哈希與經過驗證的哈希進行比較
diff -s verified.hash my.hash
-
使用 metadata.gz 重複 5 和 6
OpenSSL
參考
-build 和 -sign 生成的 .pem 文件是 PEM 文件。這裏有幾個有用的 OpenSSL
命令來操作它們:
# convert a PEM format X509 certificate into DER format: # (note: Windows .cer files are X509 certificates in DER format) $ openssl x509 -in input.pem -outform der -out output.der # print out the certificate in a human-readable format: $ openssl x509 -in input.pem -noout -text
你也可以對私鑰文件做同樣的事情:
# convert a PEM format RSA key into DER format: $ openssl rsa -in input_key.pem -outform der -out output_key.der # print out the key in a human readable format: $ openssl rsa -in input_key.pem -noout -text
錯誤/待辦事項
-
無法定義 system-wide 信任列表。
-
自定義安全策略(來自
YAML
文件等) -
生成簽名證書請求的簡單方法
-
支持 OCSP、SCVP、CRL 或其他形式的證書狀態檢查(列表按優先順序排列)
-
支持加密私鑰
-
某種semi-formal 信任層次結構(參見上麵的long-winded 解釋)
-
路徑發現(對於沒有 self-signed 根的 gem 證書鏈)- 順便說一下,由於我們沒有這個,如果
Policy#verify_root
為真(並且它適用於MediumSecurity
和HighSecurity
策略) -
更好地解釋 X509 命名(即,我們不必使用電子郵件地址)
-
榮譽 AIA 領域(見上文關於 OCSP 的說明)
-
榮譽延期限製
-
將證書鏈存儲為 PKCS#7 或 PKCS#12 文件而不是嵌入在元數據中的數組可能會更好。
原作者
保羅鄧肯 <pabs@pablotron.org> pablotron.org /
相關用法
- Ruby SecureRandom模塊用法及代碼示例
- Ruby Set flatten()用法及代碼示例
- Ruby Set.replace用法及代碼示例
- Ruby Set intersection()用法及代碼示例
- Ruby Set類用法及代碼示例
- Ruby Set.==用法及代碼示例
- Ruby Set.disjoint?用法及代碼示例
- Ruby Set size()用法及代碼示例
- Ruby Set compare_by_identity?用法及代碼示例
- Ruby Set merge()用法及代碼示例
- Ruby Set.classify用法及代碼示例
- Ruby Set add?用法及代碼示例
- Ruby Set compare_by_identity()用法及代碼示例
- Ruby Set flatten!()用法及代碼示例
- Ruby Set divide()用法及代碼示例
- Ruby Set replace()用法及代碼示例
- Ruby Set.[]用法及代碼示例
- Ruby Set.===用法及代碼示例
- Ruby Set include?()用法及代碼示例
- Ruby Set subtract()用法及代碼示例
- Ruby Set member?()用法及代碼示例
- Ruby Set intersect?()用法及代碼示例
- Ruby Set proper_subset?()用法及代碼示例
- Ruby Set difference()用法及代碼示例
- Ruby Set.-用法及代碼示例
注:本文由純淨天空篩選整理自ruby-lang.org大神的英文原創作品 Security模塊。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。