mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Follow up of #25602
Since keys are truncated, ruby 2.4 doesn't accept keys greater than their lenghts. keys of same value but different lenght and greater than key size of cipher, produce the same results as reproduced at https://gist.github.com/rhenium/b81355fe816dcfae459cc5eadfc4f6f9 Since our default cipher is 'aes-256-cbc', key length for which is 32 bytes, limit the length of key being passed to Encryptor to 32 bytes. This continues to support backwards compat with any existing signed data, already encrupted and signed with 32+ byte keys. Also fixes the passing of this value in multiple tests.
This commit is contained in:
parent
fd2446cd81
commit
ae32b69ab9
3 changed files with 41 additions and 15 deletions
|
@ -567,17 +567,19 @@ module ActionDispatch
|
|||
|
||||
class EncryptedCookieJar < AbstractCookieJar # :nodoc:
|
||||
include SerializedCookieJars
|
||||
DEFAULT_CIPHER = 'aes-256-cbc'
|
||||
|
||||
def initialize(parent_jar)
|
||||
super
|
||||
def initialize(parent_jar, cipher: DEFAULT_CIPHER)
|
||||
super(parent_jar)
|
||||
|
||||
if ActiveSupport::LegacyKeyGenerator === key_generator
|
||||
raise "You didn't set secrets.secret_key_base, which is required for this cookie jar. " +
|
||||
"Read the upgrade documentation to learn more about this new config option."
|
||||
end
|
||||
|
||||
secret = key_generator.generate_key(request.encrypted_cookie_salt || "")
|
||||
sign_secret = key_generator.generate_key(request.encrypted_signed_cookie_salt || "")
|
||||
key_len = OpenSSL::Cipher.new(cipher).key_len
|
||||
secret = key_generator.generate_key(request.encrypted_cookie_salt || '')[0, key_len]
|
||||
sign_secret = key_generator.generate_key(request.encrypted_signed_cookie_salt || '')
|
||||
@encryptor = ActiveSupport::MessageEncryptor.new(secret, sign_secret, digest: digest, serializer: ActiveSupport::MessageEncryptor::NullSerializer)
|
||||
end
|
||||
|
||||
|
|
|
@ -603,7 +603,7 @@ class CookiesTest < ActionController::TestCase
|
|||
secret = key_generator.generate_key(encrypted_cookie_salt)
|
||||
sign_secret = key_generator.generate_key(encrypted_signed_cookie_salt)
|
||||
|
||||
marshal_value = ActiveSupport::MessageEncryptor.new(secret, sign_secret, serializer: Marshal).encrypt_and_sign("bar")
|
||||
marshal_value = ActiveSupport::MessageEncryptor.new(secret[0..31], sign_secret, serializer: Marshal).encrypt_and_sign("bar")
|
||||
@request.headers["Cookie"] = "foo=#{marshal_value}"
|
||||
|
||||
get :get_encrypted_cookie
|
||||
|
@ -612,7 +612,7 @@ class CookiesTest < ActionController::TestCase
|
|||
assert_not_equal "bar", cookies[:foo]
|
||||
assert_equal "bar", cookies.encrypted[:foo]
|
||||
|
||||
encryptor = ActiveSupport::MessageEncryptor.new(secret, sign_secret, serializer: JSON)
|
||||
encryptor = ActiveSupport::MessageEncryptor.new(secret[0..31], sign_secret, serializer: JSON)
|
||||
assert_equal "bar", encryptor.decrypt_and_verify(@response.cookies["foo"])
|
||||
end
|
||||
|
||||
|
@ -624,7 +624,7 @@ class CookiesTest < ActionController::TestCase
|
|||
encrypted_signed_cookie_salt = @request.env["action_dispatch.encrypted_signed_cookie_salt"]
|
||||
secret = key_generator.generate_key(encrypted_cookie_salt)
|
||||
sign_secret = key_generator.generate_key(encrypted_signed_cookie_salt)
|
||||
json_value = ActiveSupport::MessageEncryptor.new(secret, sign_secret, serializer: JSON).encrypt_and_sign("bar")
|
||||
json_value = ActiveSupport::MessageEncryptor.new(secret[0..31], sign_secret, serializer: JSON).encrypt_and_sign("bar")
|
||||
@request.headers["Cookie"] = "foo=#{json_value}"
|
||||
|
||||
get :get_encrypted_cookie
|
||||
|
@ -636,6 +636,20 @@ class CookiesTest < ActionController::TestCase
|
|||
assert_nil @response.cookies["foo"]
|
||||
end
|
||||
|
||||
|
||||
def test_compat_encrypted_cookie_using_64_byte_key
|
||||
# Cookie generated with 64 bytes secret
|
||||
message = ["566d4e75536d686e633246564e6b493062557079626c566d51574d30515430394c53315665564a694e4563786555744f57537454576b396a5a31566a626e52525054303d2d2d34663234333330623130623261306163363562316266323335396164666364613564643134623131"].pack('H*')
|
||||
@request.headers["Cookie"] = "foo=#{message}"
|
||||
|
||||
get :get_encrypted_cookie
|
||||
|
||||
cookies = @controller.send :cookies
|
||||
assert_not_equal "bar", cookies[:foo]
|
||||
assert_equal "bar", cookies.encrypted[:foo]
|
||||
assert_nil @response.cookies["foo"]
|
||||
end
|
||||
|
||||
def test_accessing_nonexistent_encrypted_cookie_should_not_raise_invalid_message
|
||||
get :set_encrypted_cookie
|
||||
assert_nil @controller.send(:cookies).encrypted[:non_existent_attribute]
|
||||
|
@ -799,8 +813,8 @@ class CookiesTest < ActionController::TestCase
|
|||
key_generator = @request.env["action_dispatch.key_generator"]
|
||||
secret = key_generator.generate_key(@request.env["action_dispatch.encrypted_cookie_salt"])
|
||||
sign_secret = key_generator.generate_key(@request.env["action_dispatch.encrypted_signed_cookie_salt"])
|
||||
encryptor = ActiveSupport::MessageEncryptor.new(secret, sign_secret)
|
||||
assert_equal "bar", encryptor.decrypt_and_verify(@response.cookies["foo"])
|
||||
encryptor = ActiveSupport::MessageEncryptor.new(secret[0..31], sign_secret)
|
||||
assert_equal 'bar', encryptor.decrypt_and_verify(@response.cookies["foo"])
|
||||
end
|
||||
|
||||
def test_legacy_json_signed_cookie_is_read_and_transparently_upgraded_by_signed_json_cookie_jar_if_both_secret_token_and_secret_key_base_are_set
|
||||
|
@ -838,8 +852,8 @@ class CookiesTest < ActionController::TestCase
|
|||
key_generator = @request.env["action_dispatch.key_generator"]
|
||||
secret = key_generator.generate_key(@request.env["action_dispatch.encrypted_cookie_salt"])
|
||||
sign_secret = key_generator.generate_key(@request.env["action_dispatch.encrypted_signed_cookie_salt"])
|
||||
encryptor = ActiveSupport::MessageEncryptor.new(secret, sign_secret, serializer: JSON)
|
||||
assert_equal "bar", encryptor.decrypt_and_verify(@response.cookies["foo"])
|
||||
encryptor = ActiveSupport::MessageEncryptor.new(secret[0..31], sign_secret, serializer: JSON)
|
||||
assert_equal 'bar', encryptor.decrypt_and_verify(@response.cookies["foo"])
|
||||
end
|
||||
|
||||
def test_legacy_json_signed_cookie_is_read_and_transparently_upgraded_by_signed_json_hybrid_jar_if_both_secret_token_and_secret_key_base_are_set
|
||||
|
@ -877,8 +891,8 @@ class CookiesTest < ActionController::TestCase
|
|||
key_generator = @request.env["action_dispatch.key_generator"]
|
||||
secret = key_generator.generate_key(@request.env["action_dispatch.encrypted_cookie_salt"])
|
||||
sign_secret = key_generator.generate_key(@request.env["action_dispatch.encrypted_signed_cookie_salt"])
|
||||
encryptor = ActiveSupport::MessageEncryptor.new(secret, sign_secret, serializer: JSON)
|
||||
assert_equal "bar", encryptor.decrypt_and_verify(@response.cookies["foo"])
|
||||
encryptor = ActiveSupport::MessageEncryptor.new(secret[0..31], sign_secret, serializer: JSON)
|
||||
assert_equal 'bar', encryptor.decrypt_and_verify(@response.cookies["foo"])
|
||||
end
|
||||
|
||||
def test_legacy_marshal_signed_cookie_is_read_and_transparently_upgraded_by_signed_json_hybrid_jar_if_both_secret_token_and_secret_key_base_are_set
|
||||
|
@ -916,8 +930,8 @@ class CookiesTest < ActionController::TestCase
|
|||
key_generator = @request.env["action_dispatch.key_generator"]
|
||||
secret = key_generator.generate_key(@request.env["action_dispatch.encrypted_cookie_salt"])
|
||||
sign_secret = key_generator.generate_key(@request.env["action_dispatch.encrypted_signed_cookie_salt"])
|
||||
encryptor = ActiveSupport::MessageEncryptor.new(secret, sign_secret, serializer: JSON)
|
||||
assert_equal "bar", encryptor.decrypt_and_verify(@response.cookies["foo"])
|
||||
encryptor = ActiveSupport::MessageEncryptor.new(secret[0..31], sign_secret, serializer: JSON)
|
||||
assert_equal 'bar', encryptor.decrypt_and_verify(@response.cookies["foo"])
|
||||
end
|
||||
|
||||
def test_legacy_signed_cookie_is_treated_as_nil_by_signed_cookie_jar_if_tampered
|
||||
|
|
|
@ -48,6 +48,16 @@ class MessageEncryptorTest < ActiveSupport::TestCase
|
|||
assert_equal @data, @encryptor.decrypt_and_verify(message)
|
||||
end
|
||||
|
||||
def test_backwards_compat_for_64_bytes_key
|
||||
# 64 bit key
|
||||
secret = ["3942b1bf81e622559ed509e3ff274a780784fe9e75b065866bd270438c74da822219de3156473cc27df1fd590e4baf68c95eeb537b6e4d4c5a10f41635b5597e"].pack('H*')
|
||||
# Encryptor with 32 bit key, 64 bit secret for verifier
|
||||
encryptor = ActiveSupport::MessageEncryptor.new(secret[0..31], secret)
|
||||
# Message generated with 64 bit key
|
||||
message = "eHdGeExnZEwvMSt3U3dKaFl1WFo0TjVvYzA0eGpjbm5WSkt5MXlsNzhpZ0ZnbWhBWFlQZTRwaXE1bVJCS2oxMDZhYVp2dVN3V0lNZUlWQ3c2eVhQbnhnVjFmeVVubmhRKzF3WnZyWHVNMDg9LS1HSisyakJVSFlPb05ISzRMaXRzcFdBPT0=--831a1d54a3cda8a0658dc668a03dedcbce13b5ca"
|
||||
assert_equal 'data', encryptor.decrypt_and_verify(message)[:some]
|
||||
end
|
||||
|
||||
def test_alternative_serialization_method
|
||||
prev = ActiveSupport.use_standard_json_time_format
|
||||
ActiveSupport.use_standard_json_time_format = true
|
||||
|
|
Loading…
Reference in a new issue