views:

560

answers:

2

Hello all. I've got a question about how Rails handles cookie encryption/decryption.

I've got this in my config/environment.rb

  config.action_controller.session = {
    :session_key => [some key],
    :secret => [some secret]
  }

And this in config/environment/production.rb et al.:

  ActionController::Base.session_options[:session_domain] = [some
domain]

So far, so good -- as long as all my Rails apps have the same session_key and secret, and are on the same domain, they can all use that same cookie.

However, a colleague now has a JSP application (on the same domain), with which he'd like to read the cookies I have set.

So, given a secret and an encrypted cookie value, how would we decrypt it to get the contents of that cookie?

(The docs seem to indicate this is one-way SHA1 encryption by default -- http://caboo.se/doc/classes/CGI/Session/CookieStore.html -- but then how would my Rails applications read the contents of a cookie that is one-way encrypted?)

Thanks in advance for any tips/pointers/insight,

Joe

+1  A: 

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('=').last
verifier = 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.

Alex Reisner
A: 

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))

It is not encrypted at all.

Midwire
Alas, I'm using cookies for the sessions on this particular project. I don't see anything database-specific in your line to decode it."Decrypt" is the wrong word; I should have said "decode".Thanks for the suggestion.