散列的有趣之处在于,即使您从正确的字符串开始,如果这些字符串组合/编码/解码不正确,结果仍然可能完全错误。
最大的问题是这些函数中的大多数实际上都使用输入字符串的二进制表示。因此,如何解码这些字符串会产生很大的不同。请注意,当解码为 UTF-8 与 Hex 时,相同的字符串会产生完全不同的二进制文件?这意味着 Hash、ToBase64 等的结果也将完全不同。
// Result: UTF-8: 65-65-68-69
writeOutput("<br>UTF-8: "& arrayToList(charsetDecode("AADE", "UTF-8"), "-"));
// Result: HEX: -86--34
writeOutput("<br>HEX: "& arrayToList(binaryDecode("AADE", "HEX"), "-"));
可能的解决方案:
当前代码的问题在于ToBase64假定输入字符串被编码为 UTF-8。而Hash()实际上返回一个十六进制字符串。所以 ToBase64() 解码不正确。相反,使用binaryDecode和binaryEncode将哈希从十六进制转换为 base64:
resultAsHex = Hash( NONCE & TS & Hash(PW,"SHA-1"), "SHA-1");
resultAsBase64 = binaryEncode(binaryDecode(resultAsHex, "HEX"), "base64");
writeDump(resultAsBase64);
更强大的解决方案:
话虽如此,但要非常小心字符串连接和散列。因为它并不总是产生预期的结果。如果不了解更多关于这个特定 API 的信息,我无法完全确定它的预期。但是,仅使用二进制值通常更安全。不幸的是,CF 的 ArrayAppend() 函数缺乏对二进制数组的支持,但是您可以轻松地使用Apache 的 ArrayUtils类,它与 CF 捆绑在一起。
ArrayUtils = createObject("java", "org.apache.commons.lang.ArrayUtils");
// Combine binary of NONCE + TS
nonceBytes = charsetDecode(NONCE, "UTF-8");
timeBytes = charsetDecode(TS, "UTF-8");
combinedBytes = ArrayUtils.addAll(nonceBytes, timeBytes);
// Combine with binary of SECRET
secretBytes = binaryDecode( Hash(PW,"SHA-1"), "HEX");
combinedBytes = ArrayUtils.addAll(combinedBytes, secretBytes);
// Finally, HASH the binary and convert to base64
resultAsHex = hash(combinedBytes, "SHA-1");
resultAsBase64 = binaryEncode(binaryDecode(resultAsHex, "hex"), "base64");
writeDump(resultAsBase64);