Rails 从代码和终端打开不同的加密结果



>当我尝试加密来自终端的数据时,例如

echo -n "TestData" | openssl enc -aes-256-cbc -a -K C81E728D9D4C2F636F067F89CC14862C65990ABE58735B91B6B8798E8CE45F22 -iv D342F9C6310F6B21E97AB38595BD8CAA

比我收到的 Base64 编码结果是

VJwJBTtVntJvRGkD24S4wg==

但是当我使用完全相同的键和初始化向量对 rails 尝试同样的事情时

cipher = OpenSSL::Cipher::Cipher.new('aes-256-cbc')
cipher.encrypt
cipher.key = "C81E728D9D4C2F636F067F89CC14862C65990ABE58735B91B6B8798E8CE45F22"
cipher.iv = "D342F9C6310F6B21E97AB38595BD8CAA"
encrypted_data = cipher.update("TestData")
encrypted_data << cipher.final
Base64.strict_encode64(encrypted_data)

比我收到完全不同的 Base64 编码结果

qavpNrU7llgauAyyEZz/bw==

有人可以指出我错过了什么吗?

您将keyiv属性作为十六进制字符串提供,但预期的格式是原始字节。将它们转换为二进制文件会产生预期的结果,使用以下脚本:

require 'openssl'
require 'base64'
def hex_to_bin(s)
s.scan(/../).map { |x| x.hex.chr }.join
end
cipher = OpenSSL::Cipher::Cipher.new('aes-256-cbc')
cipher.encrypt
cipher.key = hex_to_bin("C81E728D9D4C2F636F067F89CC14862C65990ABE58735B91B6B8798E8CE45F22")
cipher.iv = hex_to_bin("D342F9C6310F6B21E97AB38595BD8CAA")
encrypted_data = cipher.update("TestData")
encrypted_data << cipher.final
puts Base64.strict_encode64(encrypted_data)

(hex_to_bin函数的来源:To Hex and Back (with Ruby((。

称其为encrypt.rb,这是运行它的结果:

$ ruby encrypt.rb 
encrypt.rb:8: warning: constant OpenSSL::Cipher::Cipher is deprecated
VJwJBTtVntJvRGkD24S4wg==

为了摆脱"已弃用"警告,我不得不将已弃用的类OpenSSL::Cipher::Cipher替换为OpenSSL::Cipher

密钥是短的,98304A2480DDC0FA354278936DAC2A0D7D9074650AD6是无效的密钥大小,AES 密钥的长度为 128、192 或 256 位(16、24 或 32 字节(。由于看起来密钥应该是 256 位(32 字节(,因此缺少的密钥字节将是垃圾或可能是空值,因此密钥扩展名未定义。因此不同的结果。

假设第一种情况为空填充和 PKCS#7 填充,结果是正确的: 艾斯卡尔克

第二个例子是在其他庄园填写钥匙。

解决方案是使用全长密钥。

最新更新