如何生成可以作为字符串共享的 AES-256 CBC key/iv?

How to generate a AES-256 CBC key/iv that can be shared as a string?

我正在尝试使 AES-256 CBC 加密在 PHP、Ruby 中工作(使用 SymmetricEncryption) and Javascript (using CryptoJS)。至于前两个:

<?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=='

但是根据上面的key/iv只提供128位的安全性。

PHP and Ruby take the key and IV as a binary string. They don't assume that it is Hex-encoded. So, although this key has 256 bits in it, the security is actually only 128 bits, because each character has only 4 bit in a Hex-encoded string.

因此仅使用 key/iv 的一半在 CryptoJS 中提供相同的加密结果。

CryptoJS.AES.encrypt(
    "Hello!",
    CryptoJS.enc.Utf8.parse('1234567890ABCDEF1234567890ABCDEF'),
    iv: CryptoJS.enc.Utf8.parse('1234567890ABCDEF')
).toString() // 'BAd5fmmMTvRE4Ohvf3GpCw=='

如何生成提供 256 位安全性的字符串密钥和 iv?

您使用密钥生成器,如果不可用,则使用随机数生成器来生成正确大小的密钥,在本例中为 32 字节。您可以将其提供给密码实现。然后,如果您需要十六进制,那么您可以 convertencode 将它们显式转换为十六进制。

当然,要解密(或再次加密)您首先必须 解码解析 将十六进制字符串返回到实际的二进制密钥。

基本上您会使用十六进制来表示字节或八位字节,但您永远不会直接使用十六进制。


请注意,通常不使用十六进制字符串。我只会用它们来测试代码。一般来说,密钥放在 (PKCS#12) 密钥存储中,或者它们是由密钥派生方法生成的。十六进制通常仅供人类使用,而这通常不是必需的。不编码为十六进制的原因之一是字符串有时很难从内存中删除,因此很可能十六进制密钥在使用后仍保留在内存中。