Skip to content

Instantly share code, notes, and snippets.

@tonytonyjan
Last active May 18, 2022 10:31
Show Gist options
  • Save tonytonyjan/d71f040fe1085dfcf1d4 to your computer and use it in GitHub Desktop.
Save tonytonyjan/d71f040fe1085dfcf1d4 to your computer and use it in GitHub Desktop.
session cookie decrypter for Rails
require 'cgi'
require 'json'
require 'active_support'
def verify_and_decrypt_session_cookie(cookie, secret_key_base)
cookie = CGI::unescape(cookie)
salt = 'encrypted cookie'
signed_salt = 'signed encrypted cookie'
key_generator = ActiveSupport::KeyGenerator.new(secret_key_base, iterations: 1000)
secret = key_generator.generate_key(salt)
sign_secret = key_generator.generate_key(signed_salt)
encryptor = ActiveSupport::MessageEncryptor.new(secret, sign_secret, serializer: JSON)
encryptor.decrypt_and_verify(cookie)
end
require 'openssl'
require 'base64'
require 'cgi'
require 'json'
def verify_and_decrypt_session_cookie cookie, secret_key_base
cookie = CGI.unescape(cookie)
#################
# generate keys #
#################
encrypted_cookie_salt = 'encrypted cookie' # default: Rails.application.config.action_dispatch.encrypted_cookie_salt
encrypted_signed_cookie_salt = 'signed encrypted cookie' # default: Rails.application.config.action_dispatch.encrypted_signed_cookie_salt
iterations = 1000
key_size = 64
secret = OpenSSL::PKCS5.pbkdf2_hmac_sha1(secret_key_base, encrypted_cookie_salt, iterations, key_size)
sign_secret = OpenSSL::PKCS5.pbkdf2_hmac_sha1(secret_key_base, encrypted_signed_cookie_salt, iterations, key_size)
##########
# Verify #
##########
data, digest = cookie.split('--')
raise 'invalid message' unless digest == OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA1.new, sign_secret, data)
# you better use secure compare instead of `==` to prevent time based attact,
# ref: ActiveSupport::SecurityUtils.secure_compare
###########
# Decrypt #
###########
encrypted_message = Base64.strict_decode64(data)
encrypted_data, iv = encrypted_message.split('--').map{|v| Base64.strict_decode64(v) }
cipher = OpenSSL::Cipher::Cipher.new('aes-256-cbc')
cipher.decrypt
cipher.key = secret
cipher.iv = iv
decrypted_data = cipher.update(encrypted_data)
decrypted_data << cipher.final
JSON.load(decrypted_data)
end
require 'bundler/setup'
require 'yaml'
require 'uri'
require 'json'
require 'active_support'
def verify_and_decrypt_session_cookie(cookie, secret_key_base)
cookie = URI.decode_www_form_component(cookie)
salt = 'encrypted cookie'
signed_salt = 'signed encrypted cookie'
key_generator = ActiveSupport::KeyGenerator.new(secret_key_base, iterations: 1000)
secret = key_generator.generate_key(salt)[0, ActiveSupport::MessageEncryptor.key_len]
sign_secret = key_generator.generate_key(signed_salt)
encryptor = ActiveSupport::MessageEncryptor.new(secret, sign_secret, serializer: JSON)
encryptor.decrypt_and_verify(cookie)
end
require 'openssl'
require 'base64'
require 'uri'
require 'json'
require 'yaml'
def verify_and_decrypt_session_cookie(cookie, secret_key_base)
cookie = URI.decode_www_form_component(cookie)
#################
# generate keys #
#################
# Rails.application.config.action_dispatch.encrypted_cookie_salt
encrypted_cookie_salt = 'encrypted cookie'
# Rails.application.config.action_dispatch.encrypted_signed_cookie_salt
encrypted_signed_cookie_salt = 'signed encrypted cookie'
iterations = 1000
key_size = 64
secret = OpenSSL::PKCS5.pbkdf2_hmac_sha1(secret_key_base, encrypted_cookie_salt, iterations, key_size)[0, 32]
sign_secret = OpenSSL::PKCS5.pbkdf2_hmac_sha1(secret_key_base, encrypted_signed_cookie_salt, iterations, key_size)
##########
# Verify #
##########
data, digest = cookie.split('--')
raise 'invalid message' unless digest == OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA1.new, sign_secret, data)
# you better use secure compare instead of `==` to prevent time based attact,
# ref: ActiveSupport::SecurityUtils.secure_compare
###########
# Decrypt #
###########
encrypted_message = Base64.strict_decode64(data)
encrypted_data, iv = encrypted_message.split('--').map{|v| Base64.strict_decode64(v) }
cipher = OpenSSL::Cipher.new('aes-256-cbc')
cipher.decrypt
cipher.key = secret
cipher.iv = iv
decrypted_data = cipher.update(encrypted_data)
decrypted_data << cipher.final
JSON.parse(decrypted_data)
end
@nevans
Copy link

nevans commented Mar 31, 2020

FYI: your scripts didn't work for me under rails 5.2.4, but they got me started. Here's what I wound up with: https://gist.github.com/nevans/558b69f227c243f63552a6f91915424f

@tonytonyjan
Copy link
Author

Hi, @nevans, Thanks for your work.

As the file name called rails_42_with_active_support.rb, this gist is for Rails v4 instead of v5. I checked your gist and the SO thread here: https://stackoverflow.com/questions/41474176/how-to-decrypt-a-rails-5-session-cookie-manually

They are really helpful, thank you.

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