本文簡要介紹ruby語言中 OpenSSL::Cipher類
的用法。
提供加密和解密的對稱算法。可用的算法取決於安裝的 OpenSSL
的特定版本。
列出所有支持的算法
可以通過以下方式獲得支持的算法列表
puts OpenSSL::Cipher.ciphers
實例化 Cipher
有幾種方法可以創建 Cipher
實例。通常, Cipher
算法按其名稱、 key 長度(以位為單位)和要使用的密碼模式進行分類。創建 Cipher
的最通用方法如下
cipher = OpenSSL::Cipher.new('<name>-<key length>-<mode>')
即,由各個組件名稱、鍵長度和模式的連字符連接組成的字符串。可以使用全部大寫或全部小寫的字符串,例如:
cipher = OpenSSL::Cipher.new('aes-128-cbc')
選擇加密或解密模式
對於對稱算法,加密和解密通常是非常相似的操作,這反映在不必為任一操作選擇不同的類,兩者都可以使用相同的類來完成。盡管如此,在獲得 Cipher
實例後,我們需要告訴實例我們打算用它做什麽,所以我們需要調用
cipher.encrypt
或者
cipher.decrypt
在 Cipher
實例上。這應該是創建實例後的第一次調用,否則已經設置的配置可能會在此過程中丟失。
選擇一把鑰匙
對稱加密要求加密方和解密方使用相同的 key ,並且在初始 key 建立後應作為私有信息保存。有很多方法可以創建不安全的 key ,最值得注意的是簡單地將密碼作為 key ,而無需進一步處理密碼。為特定 Cipher
創建 key 的一種簡單而安全的方法是
cipher = OpenSSL::Cipher.new('aes-256-cfb')
cipher.encrypt
key = cipher.random_key # also sets the generated key on the Cipher
如果您絕對需要使用密碼作為加密 key ,則應使用基於密碼的 key 派生函數 2 (PBKDF2),方法是借助 OpenSSL::PKCS5.pbkdf2_hmac_sha1
或 OpenSSL::PKCS5.pbkdf2_hmac
提供的函數生成 key 。
盡管有 Cipher#pkcs5_keyivgen
,但它的使用已被棄用,它隻應在遺留應用程序中使用,因為它不使用較新的 PKCS#5 v2 算法。
選擇靜脈輸液
密碼模式 CBC、CFB、OFB 和 CTR 都需要 “initialization vector” 或簡稱 IV。 ECB 模式是唯一不需要 IV 的模式,但這種模式幾乎沒有合法的用例,因為它沒有充分隱藏明文模式。所以
除非你絕對確定你絕對需要它,否則你永遠不應該使用 ECB 模式
因此,您最終會得到一個在任何情況下都明確需要 IV 的模式。雖然 IV 可以被視為公共信息,即它一旦生成就可以公開傳輸,但它仍應保持不可預測性以防止某些類型的攻擊。因此,理想情況下
始終為 Cipher 的每次加密創建一個安全的隨機 IV
應該為每個數據加密創建一個新的隨機 IV。將 IV 視為隨機數(使用一次的數字)——它是公開的,但隨機且不可預測。可以按如下方式創建安全隨機 IV
cipher = ...
cipher.encrypt
key = cipher.random_key
iv = cipher.random_iv # also sets the generated IV on the Cipher
雖然 key 通常也是一個隨機值,但作為 IV 是一個糟糕的選擇。攻擊者可以通過多種方式利用這種 IV。作為一般經驗法則,應不惜一切代價避免直接或間接暴露 key ,並且隻有在有充分理由的情況下才會出現例外情況。
調用 Cipher#final
ECB(不應使用)和 CBC 都是基於塊的模式。這意味著與其他基於流的模式不同,它們對固定大小的數據塊進行操作,因此它們需要 “finalization” 步驟來通過適當處理某種形式的填充來生成或正確解密最後一個數據塊。因此,必須將 OpenSSL::Cipher#final
的輸出添加到您的加密/解密緩衝區,否則您最終會遇到解密錯誤或截斷數據。
雖然這對於streaming-mode 密碼來說並不是真正必要的,但仍然建議應用相同的模式,即在那裏添加 Cipher#final
的輸出 - 它還使您將來可以更輕鬆地在模式之間切換。
加密和解密一些數據
data = "Very, very confidential data"
cipher = OpenSSL::Cipher.new('aes-128-cbc')
cipher.encrypt
key = cipher.random_key
iv = cipher.random_iv
encrypted = cipher.update(data) + cipher.final
...
decipher = OpenSSL::Cipher.new('aes-128-cbc')
decipher.decrypt
decipher.key = key
decipher.iv = iv
plain = decipher.update(encrypted) + decipher.final
puts data == plain #=> true
認證加密和相關數據 (AEAD)
如果使用的 OpenSSL
版本支持它,則應始終首選經過身份驗證的加密模式(例如 GCM 或 CCM),而不是任何未經身份驗證的模式。目前, OpenSSL
僅支持與關聯數據 (AEAD) 結合使用的 AE,其中在加密過程中包含額外的關聯數據以在加密結束時計算標簽。該標簽也將用於解密過程,並通過驗證其有效性,確定給定密文的真實性。
這優於未經身份驗證的模式,因為它允許檢測是否有人在加密後有效地更改了密文。這可以防止對密文的惡意修改,否則可能會被利用以對潛在攻擊者有利的方式修改密文。
如果有附加信息(例如標頭或某些元數據)也必須經過身份驗證,但不一定需要加密,則使用關聯數據。如果加密和以後的解密不需要相關數據, OpenSSL
庫仍然需要設置一個值 - 如果沒有可用的值,可以使用“”。
使用 GCM(伽羅瓦/計數器模式)的示例。您有 16 個字節 key
、12 個字節(96 位) nonce
和相關數據 auth_data
。確保不要重複使用 key
和 nonce
對。重用 nonce 會破壞 GCM 模式的安全保證。
cipher = OpenSSL::Cipher.new('aes-128-gcm').encrypt
cipher.key = key
cipher.iv = nonce
cipher.auth_data = auth_data
encrypted = cipher.update(data) + cipher.final
tag = cipher.auth_tag # produces 16 bytes tag by default
現在你是接收者。您知道 key
並已通過不受信任的網絡收到 nonce
、 auth_data
、 encrypted
和 tag
。請注意,GCM 接受 1 到 16 個字節之間的任意長度標簽。您可能還需要檢查接收到的標簽的長度是否正確,或者您允許攻擊者以 1/256 的概率為被篡改的密文偽造一個有效的單字節標簽。
raise "tag is truncated!" unless tag.bytesize == 16
decipher = OpenSSL::Cipher.new('aes-128-gcm').decrypt
decipher.key = key
decipher.iv = nonce
decipher.auth_tag = tag
decipher.auth_data = auth_data
decrypted = decipher.update(encrypted) + decipher.final
puts data == decrypted #=> true
相關用法
- Ruby CircularDependencyError類用法及代碼示例
- Ruby CircularDependencyError.new用法及代碼示例
- Ruby CStructEntity.[]=用法及代碼示例
- Ruby Context.save_history=用法及代碼示例
- Ruby CSV.header_convert用法及代碼示例
- Ruby Constants模塊用法及代碼示例
- Ruby CMath tanh()用法及代碼示例
- Ruby CSV.skip_lines用法及代碼示例
- Ruby CGI.new用法及代碼示例
- Ruby Comparable.between?用法及代碼示例
- Ruby CGI.print用法及代碼示例
- Ruby CGI.http_header用法及代碼示例
- Ruby Class類用法及代碼示例
- Ruby CMath cos()用法及代碼示例
- Ruby Complex.arg用法及代碼示例
- Ruby CSV.table用法及代碼示例
- Ruby CSV.force_quotes?用法及代碼示例
- Ruby CParser模塊用法及代碼示例
- Ruby CSV.unconverted_fields?用法及代碼示例
- Ruby ComposedSet類用法及代碼示例
- Ruby C.handle_constants用法及代碼示例
- Ruby Continuation類用法及代碼示例
- Ruby Closure類用法及代碼示例
- Ruby CStructEntity.[]用法及代碼示例
- Ruby Complex.abs2用法及代碼示例
注:本文由純淨天空篩選整理自ruby-lang.org大神的英文原創作品 Cipher類。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。