我正在做一个项目来解密 ColdFusion 中作为 URL 参数传递的 AES-128 加密字符串。
供应商采用密码短语并将其转换为有效的 AES-128 key ,“使用与使用 SHA-1 哈希函数的 Microsoft CryptDeriveKey 等效的算法”。我需要在 ColdFusion 中复制这个生成的 key ,以便我可以在我的解密()调用中使用该值。
使用 CryptDeriveKey 时,您传递加密类型、哈希类型、块长度和 0 iv 数组,它返回哈希。来源:Generating a Key from a Password
// generate an RC2 key byte[] iv = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }; byte[] key = cdk.CryptDeriveKey(“RC2”, “SHA1”, 128, iv);
在供应商的测试工具中,密码短语“test1234”产生的哈希值为:
A6455C7A24BC5E869B0DDF647238F5DA
我找到了 genAESKeyFromPW() UDF,这似乎是最接近的,但需要 CryptDeriveKey 不使用的盐。我也试过下面的代码。但是,它不起作用,因为 Hash() 没有创建有效的 AES-128 key :
<cfset generatedKey = Hash('test1234', 'SHA-1')>
<cfset decrypted=decrypt(encryptedString, generatedKey, 'AES/CBC/PKCS7Padding', 'Base64', '0')>
复制CryptDeriveKey函数需要哪些步骤?
更新:
供应商提供了此解密的 C# 示例:
public static byte[] AesDecryptBytes(byte[] cipherText, byte[] key)
{
byte[] IV = new byte[16];
AesManaged aes = new AesManaged();
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
ICryptoTransform decryptor = aes.CreateDecryptor(key, IV);
byte[] plainBytes;
using (MemoryStream memoryStream = new MemoryStream())
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Write))
{
cryptoStream.Write(cipherText, 0, cipherText.Length);
}
plainBytes = memoryStream.ToArray();
}
return plainBytes;
}
最佳答案
从我在 this documentation 中读到的内容,听起来该函数本质上是对密码二进制文件进行散列,然后对两个数组进行 XOR。我不是 100%,但我不认为他们描述的方法与 PBKDF1 或 PBKDF2 相同。
Let n be the required derived key length, in bytes. The derived key is the first n bytes of the hash value after the hash computation has been completed by CryptDeriveKey. If the hash is not a member of the SHA-2 family and the required key is for either 3DES or AES, the key is derived as follows:
- Form a 64-byte buffer by repeating the constant
0x36
64 times. Let k be the length of the hash value that is represented by the input parameter hBaseData. Set the firstk
bytes of the buffer to the result of an XOR operation of the firstk
bytes of the buffer with the hash value that is represented by the input parameterhBaseData
.- Form a 64-byte buffer by repeating the constant
0x5C
64 times. Set the firstk
bytes of the buffer to the result of an XOR operation of the firstk
bytes of the buffer with the hash value that is represented by the input parameterhBaseData
.- Hash the result of step 1 by using the same hash algorithm as that used to compute the hash value that is represented by the
hBaseData
parameter.- Hash the result of step 2 by using the same hash algorithm as that used to compute the hash value that is represented by the
hBaseData
parameter.- Concatenate the result of step 3 with the result of step 4.
- Use the first n bytes of the result of step 5 as the derived key.
CF key 生成
从 hashing 开始密码并使用 binaryDecode 将其转换为二进制文件:
hBaseData = binaryDecode(hash("test1234", "SHA1"), "hex");
使用指定的常量构建并填充两个缓冲区:
// 0x36 (i.e. 54 decimal)
buff1 = listToArray(repeatString("54,", 64));
// 0x5C (i.e. 92 decimal)
buff2 = listToArray(repeatString("92,", 64));
然后进行按位异或,将结果存储在缓冲区中:
for (k = 1; k <= arrayLen(hBaseData); k++) {
buff1[k] = BitXOR( buff1[k], hBaseData[k]);
buff2[k] = BitXOR( buff2[k], hBaseData[k]);
}
接下来 hash() 缓冲并连接结果:
hash1 = hash( javacast("byte[]", buff1), "SHA1");
hash2 = hash( javacast("byte[]", buff2), "SHA1");
combined = hash1 & hash2;
最后,提取第一个
n
字节(16 == 128 位/8)作为新 key 。由于 CF 的 hash() 函数返回十六进制(每字节总是两个字符)字符串函数可以在这里使用。keySize = 128 / 8;
newKey = left(combined, keySize *2);
结果:
A6455C7A24BC5E869B0DDF647238F5DA
在 CF 中解密
在解密之前,有几个重要的注意事项:
IV
. IV 是一个二进制数组,其长度与算法的块大小相同(AES 块大小 = 16 字节)。它必须是“...相同的值 [用于加密] 才能成功解密数据。”根据您的 API 中的描述,您的 IV 应该全为零。 (这在实践中并不好,但对于测试用例来说是可以的)。 更多详情请见Strong encryption in ColdFusion
示例:
encrypted = "1lqcm0Jiy4Rs29tz2jpuoQ==";
newKeyHex = "A6455C7A24BC5E869B0DDF647238F5DA";
keyBase64 = binaryEncode(binaryDecode(newKeyHex, "hex"), "base64");
iv = javacast("byte[]", [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]);
decrypted = decrypt(encrypted, keyBase64, "AES/CBC/PKCS5Padding", "Base64", iv);
writeOutput("<br>"& decrypted);
结果:
recordID=000001
关于encryption - 在 Coldfusion 中复制 CryptDeriveKey,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44571303/