2017-01-04 2 views

Antwort

7

Ich hatte das gleiche Problem neulich und herausgefunden, dass das generierte Geheimnis 64 Bytes lang war (auf meinem Mac), aber Rails stellt sicher, dass der Schlüssel 32 Bytes lang ist (source).

Das hat für mich gearbeitet:

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 

oder ohne 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::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 

Fühlen Sie sich frei auf dem Kern Kommentar: https://gist.github.com/mbyczkowski/34fb691b4d7a100c32148705f244d028

Verwandte Themen