【问题标题】:Unable to decrypt stored encrypted data无法解密存储的加密数据
【发布时间】:2013-09-03 08:26:19
【问题描述】:

我在尝试在 Rails 4 应用程序中加密存储的数据时遇到问题。我一直在看很多与此相关的问题,并且有很多提示,感觉就像我快到了,但不知何故它不会解密数据。这是涉及的两种方法:

def encrypt( val, pwd_name )
    cipher = OpenSSL::Cipher.new 'AES-128-CBC'
    cipher.encrypt
    iv = cipher.random_iv

    pwd = encryptor_pwds[ pwd_name ]
    salt = OpenSSL::Random.random_bytes 16
    iter = 20000
    key_len = cipher.key_len
    digest = OpenSSL::Digest::SHA256.new

    key = OpenSSL::PKCS5.pbkdf2_hmac(pwd, salt, iter, key_len, digest)
    cipher.key = key

    encrypted = cipher.update val
    encrypted << cipher.final

    encrypted = Base64.encode64( encrypted ).encode('utf-8')
    iv = Base64.encode64( iv ).encode('utf-8')
    salt = Base64.encode64( salt ).encode('utf-8')

    return { str: encrypted, iv: iv, salt: salt }
end



def decrypt( str, iv, salt, pwd_name )
    cipher = OpenSSL::Cipher.new 'AES-128-CBC'
    cipher.decrypt

    str = Base64.decode64( str )
    iv = Base64.decode64( iv )
    salt = Base64.decode64( salt )

    cipher.iv = iv

    pwd = encryptor_pwds[ pwd_name ]
    salt = salt
    iter = 20000
    key_len = cipher.key_len
    digest = OpenSSL::Digest::SHA256.new

    key = OpenSSL::PKCS5.pbkdf2_hmac(pwd, salt, iter, key_len, digest)
    cipher.key = key

    decrypted = cipher.update str
    decrypted << cipher.final
    return decrypted
end

我将读/写修改为例如:

def email=(email)
    unless email.nil?
        set = encrypt(email, :email)
        write_attribute( :email, set[:str] )
        write_attribute( :email_iv, set[:iv] )
        write_attribute( :email_salt, set[:salt] )
    else
        write_attribute( :email, nil )
    end
end

def email
    if read_attribute( :email ).nil? then read_attribute( :email ) else decrypt( read_attribute( :email ), read_attribute( :email_iv ), read_attribute( :email_salt ), :email ) end
end

但是当我尝试从中读取时,它会抛出这个OpenSSL::Cipher::CipherError: bad decrypt,似乎更多的人会遇到。

任何帮助将不胜感激!

【问题讨论】:

  • "似乎遇到了更多的人" > 那么,当您尝试其他线程/论坛建议的解决方案时发生了什么?
  • 您可以将这些功能与测试密钥/数据一起使用并在此处以十六进制打印输入/输出吗?打印出密码、盐、IV 和派生密钥。在加密/解密之前打印这些值至关重要。请注意,bad decrypt 可能意味着任何事情。错误的密钥、错误的数据、错误的编码、错误的盐、错误的密码,甚至可能是错误的 IV。
  • 您确定编码正确吗?
  • @owlstead 这个建议很棒。我一直在打印所有内容,似乎加密的电子邮件在保存到数据库之前已更改。 imichaelmiers 我很确定,是的,我之前通过创建一个小型测试脚本来验证这一点,该脚本一次完成加密和解密,在那里打印字符串值。现在我想到它也指出了存储/读取的问题。邓肯琼斯,我当然试过这些,但它们对我不起作用。
  • 原来问题出在具有 case_insensitive_keys 的 Devise gem 上,但是在保存时会触发,所以当我将 ASCII 字符串编码为 UTF-8 时,生成了一个区分大小写的字符串,但是在保存总是小写的,当然,如果你再次将它编码为 ASCII,结果字符串将与原始字符串不同。

标签: ruby-on-rails ruby encryption devise openssl


【解决方案1】:

这有点难以弄清楚,但问题不在于我的加密逻辑,而在于 Devise gem 中的过滤器。默认情况下,在保存之前设计小写电子邮件地址,但因为我正在对其进行加密和编码,所以我将区分大小写的 UTF8 字符串保存到数据库中。小写,将字符串解码回 ASCII 会导致与保存前不同的结果,这使得解密变得不可能。

现在,如果有人遇到这种情况,请在 config/initializers/devise.rb 中查找 case_insensitive_keys 设置,并确保它不包含您保存的加密密钥。请记住,如果您这样做,您最好自己将电子邮件小写或验证并禁止电子邮件中的大写字符,类似这样。

【讨论】:

    猜你喜欢
    • 2023-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-07
    • 1970-01-01
    相关资源
    最近更新 更多