[ACCEPTED]-Given the session key and secret, how can we decrypt Rails cookies?-cookies
If you pull the session.data field straight 6 from the session data stored in your app's 5 database (if you are using active_record_store 4 in your environment.rb file)
config.action_controller.session_store = :active_record_store
... here is 3 how you decode it and return the hash:
... or 2 in Rails >= 3.2 (thanks Chuck Vose)
It is 1 not encrypted at all.
Rails uses HMAC-SHA1 for encrypting cookie 10 data, which is different from a one-way 9 SHA1 encryption, as you suspected (see the Wikipedia article on HMAC for 8 an explanation). The encryption is done 7 by the
ActiveSupport::MessageVerifier class (source code is fairly readable). Here's 6 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 5 should return the session hash you expect. To 4 implement this in Java your colleague is 3 going to have to duplicate the
ActiveSupport::MessageVerifier#verify method. Source 2 code is in your gems directory (
/usr/lib/ruby/gems/1.8/gems on my system) at 1
Here's how to decrypt the session cookie 1 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
By default, Rails (before version 4) does 19 not encrypt session cookies, it only signs 18 them. To encrypt them, you need to do something 17 like this:
ActionController::Base.session_store = EncryptedCookieStore
There are multiple plugins that 16 provide that kind of encryption functionality.
So, if 15 you're not specifically using an encrypted 14 store, all the Java code needs to do is 13 verify the cookie signature and decode the 12 cookie. As Alex says in his answer, you 11 would need to duplicate the functionality 10 of
ActiveSupport::MessageVerifier#verify, and share the key with the Java application. That 9 both verifies and decodes the cookie.
If 8 you don't want to verify the signature (which 7 I do NOT recommend), you can use Midwire's 6 method of decoding from Base64 to view the 5 session hash. In Ruby, this is:
I know this 4 is old, but hope this helps somebody!
(Update: The 3 question relates to Rails 3. Starting with 2 Rails 4, session cookies are encrypted by 1 default.)
I've written a Ruby gem to handle cookies 17 managed by Rails apps. Reading its source 16 you can understand how it works and possibly 15 port it to Java so that your JSP app could 14 use that:
It's a single file with ~ 150 lines 13 of code which also handles signed only cookie 12 values and takes care of both signing/encrypting 11 and verifying/decrypting, while you seem 10 to only be concerned about decrypting. This 9 is the method for decrypting:
It worths mentioning 8 that besides the key and the secret you'll 7 also need to know which serializer is used. It 6 used to be Marshal but it seems the default 5 for newly generated apps is now JSON. If 4 Marshal was used then it may be tricky to 3 convert that code to Java as you'd have 2 to find a library which implements Ruby's 1 Marshal#load.
More Related questions