我正在尝试使用PHP,Ruby(使用SymmetricEncryption)和Javascript(使用CryptoJS)进行AES-256 CBC加密。至于前2:
<?php
openssl_encrypt(
'Hello!', 'aes-256-cbc',
'1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF',
0,
'1234567890ABCDEF1234567890ABCDEF'
); // => 'BAd5fmmMTvRE4Ohvf3GpCw=='
ruby_cipher = SymmetricEncryption::Cipher.new(
key: "1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF",
iv: "1234567890ABCDEF1234567890ABCDEF",
cipher_name: 'aes-256-cbc'
)
ruby_cipher.encrypt("Hello!") # => 'BAd5fmmMTvRE4Ohvf3GpCw=='
但根据this answer,上面的密钥/ iv仅提供128位安全性。
PHP和Ruby将密钥和IV作为二进制字符串。他们不假设它是十六进制编码的。因此,虽然这个密钥有256位,但安全性实际上只有128位,因为每个字符在十六进制编码的字符串中只有4位。
因此,仅使用一半的密钥/ iv可在CryptoJS中提供相同的加密结果。
CryptoJS.AES.encrypt(
"Hello!",
CryptoJS.enc.Utf8.parse('1234567890ABCDEF1234567890ABCDEF'),
iv: CryptoJS.enc.Utf8.parse('1234567890ABCDEF')
).toString() // 'BAd5fmmMTvRE4Ohvf3GpCw=='
如何生成提供256位安全性的字符串密钥和iv?
答案 0 :(得分:1)
使用密钥生成器,如果不可用,则使用随机数生成器生成正确大小的密钥,在本例中为32个字节。您可以将其提供给密码实现。然后,如果你需要十六进制,那么你可以将或编码显式转换为十六进制。
当然,要解密(或再次加密),您首先必须解码或解析十六进制字符串回到实际的二进制密钥。
基本上你使用十六进制来表示字节或八位字节,但你永远不会直接使用十六进制。
请注意,通常不使用十六进制字符串。我只用它们来测试代码。通常,密钥被放入(PKCS#12)密钥存储区,或者它们由密钥导出方法生成。十六进制通常仅供人类消费,这通常不是必需的。不编码为十六进制的一个原因是字符串有时难以从内存中删除,因此很可能十六进制密钥在使用后仍保留在内存中。