Skip to content

Instantly share code, notes, and snippets.

@tonytonyjan
Last active May 18, 2022 10:31

Revisions

  1. tonytonyjan revised this gist Mar 4, 2018. No changes.
  2. tonytonyjan revised this gist Mar 4, 2018. 4 changed files with 58 additions and 0 deletions.
    File renamed without changes.
    File renamed without changes.
    16 changes: 16 additions & 0 deletions rails_5_with_active_support.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,16 @@
    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
    42 changes: 42 additions & 0 deletions rails_5_with_pure_ruby.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,42 @@
    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
  3. tonytonyjan revised this gist Mar 14, 2016. 2 changed files with 15 additions and 1 deletion.
    14 changes: 14 additions & 0 deletions with_active_support.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,14 @@
    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
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,7 @@
    require 'openssl'
    require 'base64'
    require 'cgi'
    require 'JSON'
    require 'json'

    def verify_and_decrypt_session_cookie cookie, secret_key_base
    cookie = CGI.unescape(cookie)
  4. tonytonyjan revised this gist Mar 14, 2016. No changes.
  5. tonytonyjan renamed this gist Mar 14, 2016. 1 changed file with 0 additions and 0 deletions.
  6. tonytonyjan created this gist Mar 14, 2016.
    40 changes: 40 additions & 0 deletions session cookie decrypter for Rails 4+ without activesupport
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,40 @@
    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