【问题标题】:How to decrypt a Rails 5 session cookie manually?如何手动解密 Rails 5 会话 cookie?
【发布时间】:2017-05-19 08:31:45
【问题描述】:

我可以访问

  • config.action_dispatch.encrypted_cookie_salt
  • config.action_dispatch.encrypted_signed_cookie_salt
  • secrets.secret_key_base
  • 完整的 cookie 字符串(包括 --

我在 Rails 4 (Rails 4: How to decrypt rails 4 session cookie (Given the session key and secret)) 中看到了执行此操作的方法,但这些方法似乎在 Rails 5 中不起作用。

【问题讨论】:

    标签: ruby-on-rails encryption cookies ruby-on-rails-5 session-cookies


    【解决方案1】:

    前几天我遇到了同样的问题,发现生成的密钥长度为 64 字节(在我的 Mac 上),但 Rails 确保密钥长度为 32 字节(source)。

    这对我有用:

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

    或者没有ActiveSupport:

    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)[0, OpenSSL::Cipher.new('aes-256-cbc').key_len]
      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.load(decrypted_data)
    end
    

    请随意评论要点:https://gist.github.com/mbyczkowski/34fb691b4d7a100c32148705f244d028

    【讨论】:

      【解决方案2】:

      这是@matb 答案的 Rails 5.2 变体,它处理修改后的配置、加密和序列化:

      require 'cgi'
      require 'active_support'
      
      def verify_and_decrypt_session_cookie(cookie, secret_key_base = Rails.application.secret_key_base)
        cookie = CGI::unescape(cookie)
        salt   = 'authenticated encrypted cookie'
        encrypted_cookie_cipher = 'aes-256-gcm'
        serializer = ActiveSupport::MessageEncryptor::NullSerializer
      
        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)
      
        encryptor.decrypt_and_verify(cookie)
      end
      

      同样在https://gist.github.com/inopinatus/e523f36b468f94cf6d34410b73fef15e

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-05-03
        • 2010-12-28
        • 2016-07-08
        • 2013-10-14
        • 1970-01-01
        • 1970-01-01
        • 2015-12-19
        • 2013-04-28
        相关资源
        最近更新 更多