encryption - 在 Coldfusion 中复制 CryptDeriveKey

标签 encryption coldfusion

我正在做一个项目来解密 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:

  1. 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 first k bytes of the buffer to the result of an XOR operation of the first k bytes of the buffer with the hash value that is represented by the input parameter hBaseData.
  2. Form a 64-byte buffer by repeating the constant 0x5C 64 times. Set the first k bytes of the buffer to the result of an XOR operation of the first k bytes of the buffer with the hash value that is represented by the input parameter hBaseData.
  3. 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.
  4. 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.
  5. Concatenate the result of step 3 with the result of step 4.
  6. 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 中解密

在解密之前,有几个重要的注意事项:
  • CF 的加密/解密函数要求将 key 编码为 base64。上面生成的 key 是十六进制格式。所以必须先转换:
  • “PKCS7Padding”对 CF/Java 无效。 Instead use PKCS5Padding .
  • “CBC”模式总是需要一个 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/

    相关文章:

    ColdFusion 10 自动更新未得到应用

    java - 使用 Java 解密 OpenSSL PEM 编码的 RSA 私钥?

    python - str不可调用sendto python

    c# - 大量数据的最佳加密(速度至关重要)?

    postgresql - 加密postgresql中的数据

    coldfusion - 通过循环结构插入到表中

    c - 在 Eclipse 中编译 C 语言凯撒密码时遇到困难

    Coldfusion 动态变量 (?) 解析为 SQL 查询

    javascript - 将 Duo Web 2 因素身份验证与 ColdFusion 集成

    html - 通过 HTML 隐藏输入传递 ColdFusion 变量