无法解密存储的加密数据

时间:2013-08-30 14:48:02

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

我正在尝试在我的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

非常感谢任何帮助!

1 个答案:

答案 0 :(得分:3)

这一点有点棘手,但问题不在于我的加密逻辑,而在Devise gem中有一个过滤器。在默认保存之前设计小写电子邮件地址,但因为我正在加密和编码它们,我将区分大小写的UTF8字符串保存到数据库。低级,将字符串解码回ASCII导致与保存之前的结果不同,这使得解密成为不可能。

现在,如果有人遇到此问题,请在case_insensitive_keys中查找config/initializers/devise.rb设置,并确保其中不包含您要加密的密钥。请记住,如果你这样做,你最好自己小写电子邮件或验证并禁止在电子邮件中使用大写字符,就像那样。