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

时间:2016-10-14 19:28:14

标签: encryption hex aes encryption-symmetric

我正在尝试使用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?

1 个答案:

答案 0 :(得分:1)

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

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

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

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