Given the session key and secret, how can we decrypt Rails cookies? Given the session key and secret, how can we decrypt Rails cookies? ruby ruby

Given the session key and secret, how can we decrypt Rails cookies?


If you pull the session.data field straight from the session data stored in your app's database (if you are using active_record_store in your environment.rb file)

config.action_controller.session_store = :active_record_store

... here is how you decode it and return the hash:

Marshal.load(ActiveSupport::Base64.decode64(@session.data))

... or in Rails >= 3.2 (thanks Chuck Vose)

Marshal.load(Base64.decode64(@session.data))

It is not encrypted at all.


Rails uses HMAC-SHA1 for encrypting cookie data, which is different from a one-way SHA1 encryption, as you suspected (see the Wikipedia article on HMAC for an explanation). The encryption is done by the ActiveSupport::MessageVerifier class (source code is fairly readable). Here's an example based on a test Rails app:

secret = 'b6ff5a9c3c97bf89afe9a72e6667bafe855390e8570d46e16e9760f6394' +  '4ab05577b211ec2f43f6c970441518f0241775499bde055078f754c33b62f68ba27ca'cookie = "_test_session=BAh7CCIYdXNlcl9jcmVkZW50aWFsc19pZGkGIhV1c2VyX2NyZW" +  "RlbnRpYWxzIgGAMzBlODkxZDQ2MWZhNjFkMDFmNzczMmJjNDdjMjIwZGFjMTY2NWEwNDMwZ" +  "DVjMmUxOWY5MDFjMjQ5NWQ4OTM1OGZlMzE3NzRiZTFiZjM1ZTVlZDY2ZGUzYTkwOWZjZTgw" +  "NTFlNGUxZWI0MTUzYTRjODZiMGZmMzM3NzliM2U3YzI6D3Nlc3Npb25faWQiJTgxNzk0Yjd" +  "kN2IxYzRjMDE0M2QwOTk5NTVjZjUwZTVm--25c8f3222ab1be9f2394e2795a9f2557b06d0a92"session = cookie.split('=').lastverifier = ActiveSupport::MessageVerifier.new(secret, 'SHA1')verifier.verify(session)

This should return the session hash you expect. To implement this in Java your colleague is going to have to duplicate the ActiveSupport::MessageVerifier#verify method. Source code is in your gems directory (/usr/lib/ruby/gems/1.8/gems on my system) at activesupport-2.3.5/lib/active_support/message_verifier.rb.


Here's how to decrypt the session cookie in Rails 4

def decrypt_session_cookie(cookie)  cookie = CGI.unescape(cookie)  config = Rails.application.config  encrypted_cookie_salt = config.action_dispatch.encrypted_cookie_salt               # "encrypted cookie" by default  encrypted_signed_cookie_salt = config.action_dispatch.encrypted_signed_cookie_salt # "signed encrypted cookie" by default  key_generator = ActiveSupport::KeyGenerator.new(config.secret_key_base, iterations: 1000)  secret = key_generator.generate_key(encrypted_cookie_salt)  sign_secret = key_generator.generate_key(encrypted_signed_cookie_salt)  encryptor = ActiveSupport::MessageEncryptor.new(secret, sign_secret)  encryptor.decrypt_and_verify(cookie)end

http://big-elephants.com/2014-01/handling-rails-4-sessions-with-go/