ruby-on-rails - empezar - ruby on rails tutorial español
¿Cómo descifrar una cookie de sesión de Rails 5 manualmente? (1)
Tengo acceso a
config.action_dispatch.encrypted_cookie_salt
-
config.action_dispatch.encrypted_signed_cookie_salt
-
secrets.secret_key_base
- la cadena de cookies completa (incluyendo
--
)
Veo formas de hacerlo en Rails 4 ( Rails 4: Cómo descifrar los rieles de la cookie de 4 sesiones (Dada la clave de sesión y el secreto) ), pero parece que no funcionan en Rails 5.
El otro día tuve el mismo problema y descubrí que el secreto generado tenía 64 bytes de longitud (en mi mac), pero Rails asegura que la clave tiene 32 bytes de longitud ( fuente ).
Esto me ha funcionado:
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
O sin 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
Siéntase libre de comentar sobre la esencia: https://gist.github.com/mbyczkowski/34fb691b4d7a100c32148705f244d028