Authenticated Encryption should check for tag length
メンテナーはふだん 1 日以内に返信
まだ誰も着手していません。
評価
- 難易度
- 5/5
- 見積もり時間
- 1週間以上
- 初心者へのやさしさ
- 30/100
- issue の種類
- 機能追加
- 明瞭さ
- おおむね明確
- 活発さ
- 停滞
- 領域
- cryptography, security
調査の方向性
まず、AES-GCM における既存の Cipher#auth_tag と #final の動作を、現在 CipherError がどのように発生させられているかも含めて追跡します。要求されている auth_tag_len の動作とドキュメント要件を確認し、その後、暗号化と復号のパスを比較します。API 提案が解決され、タグ長が仕様どおりにチェックされ、関連する動作がドキュメント化されてテストでカバーされれば完了です。
索引モデルが issue の本文から書いたものです。
説明
The current API for using ciphers with Authenticated Encryption (currently only AES-GCM) is rather misleading and quickly leads to subtle bugs related to the length of auth_tag.
In particular, the current implementation will not check for the length of the auth_tag. Because GCM mode allows arbitrary sizes of the auth_tag up to 128 bytes, only a single byte needs to be supplied to make the authentication pass. This means that an attacker needs at most 256 attempts in order to forge a valid auth_tag.
data = 'secret'
cipher = OpenSSL::Cipher.new('aes-128-gcm')
cipher.encrypt
key = cipher.random_key
iv = cipher.random_iv
cipher.auth_data = 'auth_data'
ciphertext = cipher.update(data) + cipher.final
auth_tag = cipher.auth_tag
auth_tag = auth_tag[0] # single byte is sufficient
cipher = OpenSSL::Cipher.new('aes-128-gcm')
cipher.decrypt
cipher.key = key
cipher.iv = iv
cipher.auth_tag = auth_tag
cipher.auth_data = 'auth_data'
data = cipher.update(ciphertext) + cipher.final
# NO error raised
Currently, the only way to prevent such attacks is to manually assert the correct auth_tag length when decrypting/authenticating.
raise 'incorrect auth_tag length' unless auth_tag.length == 16
I suggest the following improvements:
Documentation should mention the importance of manually checking auth_tag length
This can/should be done immediately even if the API should not change.
Authentication tag length should be an input parameter to the cipher
To improve the usability of the API and unburden users from performing additional manual checks without compromising security, I suggest to add an auth_tag_len accessor. This can be used to determine the size of the auth_tag both when generating and when authenticating the auth_tag. The default value should be 16 bytes (see below).
#auth_tag should use auth_tag_len to determine the output length
During encryption:
If no parameter is given, #auth_tag should return an authentication tag according to the length configured in auth_tag_len.
If a length parameter is given, #auth_tag should use the supplied parameter to determine the length of the authentication tag. Although this parameter is not as useful any more it should be kept for backwards compatibility. Maybe it should be deprecated.
Currently the API supports different tag lengths by passing the length parameter to #auth_tag. This currently defaults to 16 bytes, which should be the default value for auth_tag_len in order to keep backwards compatibility.
#final should use auth_tag_len to assert the correct length of the auth_tag
During decryption:
auth_tag_len should be used to assert that the supplied auth_tag has the correct length. The big difference to the existing API lies here, because users need to actively change the value of auth_tag_len in order to allow shorter tags.
When the check fails, an OpenSSL::Cipher::CipherError should be raised. The same type of error is already raised when authentication fails, so existing users should be fine without having to touch their error handling. A descriptive error message should be helpful. In order to distinguish between such errors and "actual" verification errors, we could also add a descriptive message for the latter.
I'd be happy to implement these changes, but I wanted to discuss them first.
For reference: This issue was copied over from the Ruby Issue Tracker https://bugs.ruby-lang.org/issues/12582
- 主要言語
- C
- スター
- 276
- フォーク
- 200
- 平均マージ
- 15時間 27分
- マージ済み PR(30日)
- 7
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートなし
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
ruby/openssl のほかの issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
ruby/openssl#1116 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 3/5 1〜2日 初心者へのやさしさ 55/100
ruby/openssl#1118 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 4/5 3〜5日 初心者へのやさしさ 48/100
ruby/openssl#1082 · コメント 4 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 5/5 1週間以上 初心者へのやさしさ 35/100
ruby/openssl#1075 · コメント 4 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 4/5 3〜5日 初心者へのやさしさ 35/100
ruby/openssl#1038 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
BasedHardware/omi#20401 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 1/5 1時間未満 初心者へのやさしさ 75/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
php/frankenphp#2688 ·
メンテナーはふだん 1 日以内に返信
-
area/ysql kind/bug priority/medium
難易度 2/5 1〜3時間 初心者へのやさしさ 86/100
yugabyte/yugabyte-db#34584 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 88/100
メンテナーはふだん 1 日以内に返信