Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save wildjcrt/6359713fa770d277927051fdeb30ebbf to your computer and use it in GitHub Desktop.
Save wildjcrt/6359713fa770d277927051fdeb30ebbf to your computer and use it in GitHub Desktop.
Decrypt Rails 6.0 beta session cookies
require 'cgi'
require 'active_support'
def verify_and_decrypt_session_cookie(cookie, secret_key_base = Rails.application.secret_key_base)
config = Rails.application.config
cookie = CGI::unescape(cookie)
salt = config.action_dispatch.authenticated_encrypted_cookie_salt
encrypted_cookie_cipher = config.action_dispatch.encrypted_cookie_cipher || 'aes-256-gcm'
# serializer = ActiveSupport::MessageEncryptor::NullSerializer # use this line if you don't know your serializer
serializer = ActionDispatch::Cookies::JsonSerializer
key_generator = ActiveSupport::KeyGenerator.new(secret_key_base, iterations: 1000)
key_len = ActiveSupport::MessageEncryptor.key_len(encrypted_cookie_cipher)
secret = key_generator.generate_key(salt, key_len)
encryptor = ActiveSupport::MessageEncryptor.new(secret, cipher: encrypted_cookie_cipher, serializer: serializer)
session_key = config.session_options[:key].freeze
encryptor.decrypt_and_verify(cookie, purpose: "cookie.#{session_key}")
end
@tonekk
Copy link

tonekk commented Jun 21, 2024

In case anyone ever needs this, pre Rails 5.2 session cookies are decoded like this:

  def self.decrypt_cookie(cookie, app_secret)
    token_hashed = OpenSSL::PKCS5.pbkdf2_hmac_sha1(app_secret, "encrypted cookie", 1000, 32)
    encrypted_message = Base64.decode64(cookie).split("--")[0]
    decoded_cookie = Base64.strict_decode64(encrypted_message)
    cipher = OpenSSL::Cipher.new("aes-256-cbc")
    cipher.key = token_hashed
    cipher.update(decoded_cookie)
  end

Rails 5.2 introduced use_authenticated_cookie_encryption, which changed the algorithm from aes-256-cbc (old) to aes-256-gcm (new). See here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment