openssl aes encryption bash command != ruby openssl aes encr



我试图使用AES加密相同的文本/相同的密钥和iv。我使用bash方法和ruby的openssl stdlib,我b64编码加密的结果。但结果是不同的!我想知道为什么。以下是我所做的:

Ruby (1.9.3-p448)

data = "foobar"
key = ["a8f9f5c5b4c42c75e255a73b6be311e1"].pack("H*")
cipher = OpenSSL::Cipher::AES.new(128, :CBC)
cipher.encrypt
cipher.key = key
iv = cipher.random_iv
enc = cipher.update(data) + cipher.final
Base64.strict_encode64(enc)
cipher_key_hex = key.each_byte.map { |b| b.to_s(16) }.join
iv_hex = iv.each_byte.map { |b| b.to_s(16) }.join
Bash

-iv参数设置为上面计算的iv_hex值。

$ echo -n 'foobar' > foobar.txt
$ openssl enc -aes-128-cbc -base64 -in foobar.txt -K a8f9f5c5b4c42c75e255a73b6be311e1 -iv 5dc7ff87987c5a25ae73433f11bd6fa

=========================================

我仔细检查了两种方法的静脉注射是相同的。

Ruby输出: rbRIW7iTsNC6LttBQ+Amzg==

Bash输出: CcSs1+ssEu8FYkcspLeCWw==

我错过了什么?

问题是b.to_s不会每字节返回两个字符。这意味着任何小于16的字节值将被转换为一个字节,如果这些字节被连接起来,那么不同字节的十六进制数字将被组合在一起,导致无效的IV或key。这个事实是由加密API隐藏的,它可以将密钥和IV填充到正确的大小,而不是拒绝它们(它应该)。

您可以使用unpack("H*")代替将字节正确编码为十六进制。这也很好地对称pack("H*")用于解码十六进制值。

最新更新