Skip to content

Commit

Permalink
Verify the GCM auth tag length
Browse files Browse the repository at this point in the history
As described in ruby/openssl#63 without this check, 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 authentication tag.

The JWE spec example prescribes 128 bits (16 bytes) for the tag: https://tools.ietf.org/html/rfc7516#section-3.3
  • Loading branch information
bdewater committed Apr 30, 2018
1 parent 88aec97 commit 3393f39
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 0 deletions.
2 changes: 2 additions & 0 deletions lib/json/jwe.rb
Expand Up @@ -48,6 +48,8 @@ def decrypt!(private_key_or_secret, algorithms = nil, encryption_methods = nil)
cipher.key = encryption_key
cipher.iv = iv # NOTE: 'iv' has to be set after 'key' for GCM
if gcm?
# https://github.com/ruby/openssl/issues/63
raise DecryptionFailed.new('Invalid authentication tag') if authentication_tag.length < 16
cipher.auth_tag = authentication_tag
cipher.auth_data = auth_data
end
Expand Down
24 changes: 24 additions & 0 deletions spec/json/jwe_spec.rb
Expand Up @@ -169,6 +169,24 @@
end
end

shared_examples_for :verify_gcm_authentication_tag do
let(:jwe_string) do
_jwe_ = JSON::JWE.new plain_text
_jwe_.alg, _jwe_.enc = alg, enc
_jwe_.encrypt! key
header, key, iv, cipher_text, auth_tag = _jwe_.to_s.split('.')
truncated_auth_tag = Base64.urlsafe_decode64(auth_tag).slice(0..-2)
truncated_auth_tag = Base64.urlsafe_encode64(truncated_auth_tag, padding: false)
[header, key, iv, cipher_text, truncated_auth_tag].join('.')
end

it do
expect do
jwe.decrypt! key
end.to raise_error JSON::JWE::DecryptionFailed
end
end

shared_examples_for :unexpected_algorithm_for_decryption do
it do
expect do
Expand All @@ -193,6 +211,7 @@
let(:enc) { :A128GCM }
if gcm_supported?
it_behaves_like :decryptable
it_behaves_like :verify_gcm_authentication_tag
else
it_behaves_like :gcm_decryption_unsupported
end
Expand All @@ -202,6 +221,7 @@
let(:enc) { :A256GCM }
if gcm_supported?
it_behaves_like :decryptable
it_behaves_like :verify_gcm_authentication_tag
else
it_behaves_like :gcm_decryption_unsupported
end
Expand All @@ -226,6 +246,7 @@
let(:enc) { :A128GCM }
if gcm_supported?
it_behaves_like :decryptable
it_behaves_like :verify_gcm_authentication_tag
else
it_behaves_like :gcm_decryption_unsupported
end
Expand All @@ -235,6 +256,7 @@
let(:enc) { :A256GCM }
if gcm_supported?
it_behaves_like :decryptable
it_behaves_like :verify_gcm_authentication_tag
else
it_behaves_like :gcm_decryption_unsupported
end
Expand Down Expand Up @@ -262,6 +284,7 @@
let(:key_size) { 16 }
if gcm_supported?
it_behaves_like :decryptable
it_behaves_like :verify_gcm_authentication_tag
else
it_behaves_like :gcm_decryption_unsupported
end
Expand All @@ -272,6 +295,7 @@
let(:key_size) { 32 }
if gcm_supported?
it_behaves_like :decryptable
it_behaves_like :verify_gcm_authentication_tag
else
it_behaves_like :gcm_decryption_unsupported
end
Expand Down

0 comments on commit 3393f39

Please sign in to comment.