我正在尝试使用ColdFusion 10遵循SagePay 3.00中加密字段的规范。
要求是使用提供的密码作为密钥和初始化向量,在CBC模式下使用PKCS#5填充将字符串加密为AES(块大小为128位),并将结果编码为十六进制。
"使用提供的密码"这导致了问题。
目前我有
myStr = 'assortednamevaluepairsetc';
providedPassword = 'abcdefghijklmnop';
myCrypt = Encrypt(myStr,providedPassword,'AES/CBC/PKCS5Padding','HEX',providedPassword,1);
但由于SagePay给出的值导致错误而无法正常工作 - "指定的密钥不是此加密的有效密钥:无效的AES密钥长度"因为它只有16个字符长
根据CF文档,你需要使用generateSecretKey来保证AES的密钥长度,所以我试过这个但是虽然它给出了结果,但它在加密方面不是正确的结果
myStr = 'assortednamevaluepairsetc';
providedPassword = 'abcdefghijklmnop';
mySecret = GenerateSecretKey('AES');
myCrypt = Encrypt(myStr,mySecret,'AES/CBC/PKCS5Padding','HEX',providedPassword,1);
感谢任何帮助。
答案 0 :(得分:4)
使用generateSecretKey 保证AES的密钥长度
该功能仅在您需要生成完全新加密密钥时使用。你已经有一个。 generateSecretKey
的主要目的是确保您生成强大的加密密钥,即sufficiently random。
不起作用,因为SagePay给出的值导致了 错误 - “指定的密钥不是此加密的有效密钥:无效 AES密钥长度“仅为16个字符
AES的密钥长度16 bytes (ie 128 bits)是可以接受的。问题是encrypt()期望“密钥”是base64编码的字符串,比普通字符串长大约三十三.3%。当你调用encrypt(..)时,CF将提供的“key”字符串解码为字节,即基本上这样做:
<cfset keyBytes = binaryDecode(yourPassword, "base64")>
<cfoutput>length = #arrayLen(keyBytes)# bytes</cfoutput>
由于您的密码字符串不是base64编码的,因此生成的密钥长度太小,即(12)而不是(16)字节。因此错误信息。
解决方案是首先对其进行base64编码。 如何取决于字符串的编码。 It sounds like it is just a plain text string(希望是sufficiently random one...)。如果是这样,使用charsetDecode解码相关字符集中的字符串(即utf-8等),然后将binaryEncode解码为base64:
<cfset keyIVBytes = charsetDecode(yourKeyString, "utf-8")>
<cfset base64Key = binaryEncode(keyIVBytes, "base64")>
此外,iv
参数应为二进制。由于key
和iv
是同一个,因此只需使用上一步中的字节数组。另外,删除iterations
参数,因为它不适用。通过这些更改,它应该按预期工作:
encrypt(myStr, base64Key,"AES/CBC/PKCS5Padding", "hex", keyIVBytes)
注意:我不是加密专家,但......使用密钥作为iv是NOT a great idea ...可能想与他们核实是否还有其他选项。