如何使用 OpenSSL::Cipher 加密 UTF-8 字符串中的数据?

Posted

技术标签:

【中文标题】如何使用 OpenSSL::Cipher 加密 UTF-8 字符串中的数据?【英文标题】:How to encrypt data in a UTF-8 string using OpenSSL::Cipher? 【发布时间】:2012-06-18 01:12:39 【问题描述】:

在 Rails 3.0 (Ruby 1.9.2) 应用程序中,我尝试使用以下方式加密一些数据:

cipher = OpenSSL::Cipher.new 'aes-256-cbc'
cipher.encrypt
cipher.key = cipher.random_key
cipher.iv = cipher.random_iv

encrypted = cipher.update 'most secret data in the world'
encrypted << cipher.final

这将进入一个 UTF-8 数据库。我的问题是

> encrypted.encoding
 => #<Encoding:ASCII-8BIT>

> encrypted.encode 'utf-8'
Encoding::UndefinedConversionError: "\xF7" from ASCII-8BIT to UTF-8

如何获取 UTF-8 加密字符串?

【问题讨论】:

【参考方案1】:

解决方法是将ASCII-8BIT字符串转换为Base64,然后编码为UTF-8。

cipher = OpenSSL::Cipher.new 'aes-256-cbc'
cipher.encrypt
cipher.key = cipher.random_key
cipher.iv = cipher.random_iv

encrypted = cipher.update 'most secret data in the world'
encrypted << cipher.final

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

一旦持久化并从数据库中检索,

decoded = Base64.decode64 encoded.encode('ascii-8bit')

最后解密。


PS:如果你好奇:

cipher = OpenSSL::Cipher.new 'aes-256-cbc'
cipher.decrypt
cipher.key = random_key
cipher.iv = random_iv

decrypted = cipher.update encoded
decrypted << cipher.final

> decrypted
 => 'most secret data in the world'

【讨论】:

» encoded = Base64.encode64('Tromsø').encode('utf-8') =&gt; "VHJvbXPDuA==\n" » Base64.decode64(encoded.encode('ascii-8bit')) =&gt; "Troms\xC3\xB8" 谢谢你,拯救了我的一天!【参考方案2】:

我相信你最好的选择是使用force_encoding找到here。

> encrypted.encoding
  => #<Encoding:ASCII-8BIT>

> encrypted.force_encoding "utf-8"

> encrypted.encoding
  => #<Encoding:UTF-8>

【讨论】:

.encode 从 ASCII-8BIT 到 UTF-8 失败,所以 .force_encoding 只会生成一个无效的字节序列。

以上是关于如何使用 OpenSSL::Cipher 加密 UTF-8 字符串中的数据?的主要内容,如果未能解决你的问题,请参考以下文章

加密空字符串

ruby 实现java中的aes 加密解密

轨道加密/解密

Conjur quickstart创建myConjurAccount,显示rake中止了! OpenSSL :: Cipher :: CipherError:

QT:AES-256-CBC 根据 PHP 代码在 C++ 中加密/解密

php7 AES IOS Android