我正在使用ColdFusion 9
参考Ben Nadel在his blog上的优秀作品,我尝试了
ucase(digestUtils.sha512(imageBinary))
对于SHA-512哈希我感到很害怕:
找不到sha512方法。要么没有方法 指定的方法名称和参数类型或sha512方法是 重载了ColdFusion无法破译的参数类型 可靠。 ColdFusion找到了与提供的匹配的0个方法 参数。如果这是一个Java对象并且您验证了该方法 存在,使用javacast函数来减少歧义。
现在我知道sha512确实作为一种方法存在,因为我看到它here,但当我执行
时cfdump var="#digestUtils#"
我只得到:
md5(byte[]) byte[]
md5(java.lang.String) byte[]
md5Hex(byte[]) java.lang.String
md5Hex(java.lang.String) java.lang.String
sha(java.lang.String) byte[]
sha(byte[]) byte[]
shaHex(java.lang.String) java.lang.String
shaHex(byte[]) java.lang.String
其他方法怎么了?我想我必须尝试其他的东西。
请使用ColdFusion解决方案提供建议。 ColdFusion / Java解决方案也可以。 我正在尝试编写一个SSO应用程序,第三方人员向我提供URL参数。我已成功解码第一个参数以获取我的XML Post。我现在需要采用第二个参数,即哈希有效负载,并通过算法确保我的第一个参数没有被篡改。
====== 编辑从这里开始:好的,我尝试再次编写代码无济于事。
算法听起来很简单。但是试图实施它就是杀了我。
1. compute the hash string value of the XMLPost string above:
a. convert the base64 salt string to a UTF-8 byte array.
b. convert the base64 XML payload string to a UTF-8 byte array.
c. create a new byte array consisting of the XML payload bytes from step b, appended with the salt bytes from step a.
d. perform a SHA512 hash on the concatenated byte array from step c, which results in a hashed byte array.
e. create a new byte array consisting of the hashed bytes from step d, appended with the salt bytes from step a.
f. convert the result of step e to a base64-encoded string and should be the value of query string parameter "h" payload hash.
xmlPost是由我的第三方人员创建的: 此XML有效内容字符串已转换为UTF-8字节数组,然后将其转换为base-64字符串。生成的base-64字符串是my xmlPost的值。
所以我这样做:
<code>
<cfset xmlPost = urlDecode("PD94bWwgdmVyc2lvbj0iMS4wIj8%2bPEVzdG9yZVNzb0N1c3RvbWVyIHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiIHhtbG5zOnhzZD0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEiPjxDdXN0b21lcklkPjExMjk0MDwvQ3VzdG9tZXJJZD48RGVhbGVyQ29kZT5OODg4ODg8L0RlYWxlckNvZGU%2bPFBvaW50QmFsYW5jZT4yODA8L1BvaW50QmFsYW5jZT48Rmlyc3ROYW1lPkZhaXRoPC9GaXJzdE5hbWU%2bPExhc3ROYW1lPkh1dHVsYTwvTGFzdE5hbWU%2bPC9Fc3RvcmVTc29DdXN0b21lcj4%3d") />
<cfset salt = "3dfjh674!MujErf98344@090" />
<cfset payload_hash = urlDecode("EtLDRJfcRESFKpY4OGZZnRSN2THqT%2bEelzOuXVU06jotd2kE4yKnlYay7BqyAdcUSATRgSMaHxZa6uBqKKd9rjNkZmpoNjc0IU11akVyZjk4MzQ0QDA5MA%3d%3d") />
<cfset strXML = ToString( ToBinary( xmlpost ) ) /> <!--- to get actual XML --->
<!--- base64 encoding returns a byte array --->
<cfset saltByteArray = toBase64( salt, "utf-8" ) />
<cfset xmlpostByteArray = toBase64( xmlPost, "utf-8" ) />
<!--- append salt to xmlpost --->
<cfset xmlpostsaltByteArray = xmlpostByteArray & saltByteArray />
<!--- now let us perform a sha512 hash on this concatenated byte array --->
<cfscript>
// Create an instance of our DigestUtils class
digestUtils = createObject("java","org.apache.commons.codec.digest.DigestUtils");
// I hash a byte array using the given algorithm and return a
// 32-character Hexadecimal string. Home-made hash function for CF9 and earlier
function hashBytes( bytes, algorithm = "SHA-512" ){
// Get our instance of the digest algorithm that we'll use
// to hash the byte array.
var messageDigest = createObject( "java", "java.security.MessageDigest" ).getInstance( javaCast( "string", algorithm ) );
// Get the digest for the given byte array. This returns the
// digest (i.e., hash) in byte-array format.
var digest = messageDigest.digest( bytes );
// Now that we have our digested byte array (i.e., our hash as another byte
// array), we have to convert that into a HEX string. So, we'll need a HEX buffer.
var hexBuffer = [];
// Each integer in the byte digest needs to be converted into
// a HEX character (with possible leading zero).
for (byte =1 ;byte LTE ArrayLen(digest);byte = byte + 1) {
//for ( var byte in digest){
// Get the hex value for this byte. When converting the
// byte, only use the right-most 8 bits (last 8 bits of the integer)
// otherwise the sign of the byte can create oddities
var tail = bitAnd( 255, byte );
// Get the hex-encoding of the byte.
var hex = ucase( formatBaseN( tail, 16 ) );
// In order to make sure that all of the HEX characters
// are two-digits, we have to prepend a zero for any
// value that was originally LTE to 16 (the largest value
// that won't result in two HEX characters).
arrayAppend( hexBuffer, (tail <= 16 ? ("0" & hex) : hex) );
}
// Return the flattened character buffer.
return( arrayToList( hexBuffer, "" ) );
}
// Get the hash of the byte array using our hashBytes() function
hashByteArray = hashBytes( xmlpostsaltByteArray );
</cfscript>
<!--- The hashByteArray is in HEX format now. Convert to binary --->
<!--- You must binary decode the hashed string before converting it to binary --->
<cfset hashByteArray = toBase64( BinaryDecode( hashByteArray, 'HEX' ) ) />
<!--- The final step is to append this new hashbytearray with the salt byte array --->
<cfset hashByteArray = hashByteArray & saltByteArray />
<!--- now convert this value to a base64 encoded string --->
<cfset hashByteArray2 = toBase64( hashByteArray )/>
以下是我的strXML变量:
Actual xml structure converted from base 64 to string:
<?xml version="1.0"?><EstoreSsoCustomer xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><CustomerId>112940</CustomerId><DealerCode>N88888</DealerCode><PointBalance>280</PointBalance><FirstName>Faith</FirstName><LastName>Hutula</LastName></EstoreSsoCustomer>
最终值hasByteArray2甚至与payload_hash
远程相似这是我第一次这样做,几十年前我对散列,字节数组和字符转换的理解就飞出了窗外。
我做错了什么?
谢谢 信仰斯隆
答案 0 :(得分:3)
DigestUtils.sha512。 ColdFusion 9使用旧版本1.3。这就是找不到该方法的原因。
使用基于MessageDigest
的其他功能。请务必传递正确的算法,即:
imageHash = hashBytes( imageBinary, "SHA-512" );
更新:根据更新的代码,某些说明可能会有点误导。我相信它们只是将xml
和salt
字符串从其给定的编码(base64和utf-8)解码为字节数组,而不是字符串:
// note: salt value has invalid characters for base64
// assuming it is a plain utf-8 string
saltArray = charsetDecode(salt, "utf-8");
xmlByteArray = binaryDecode(xmlPost, "base64");
然后合并两个二进制数组(参见自定义函数)
mergedBytes = mergeArrays( xmlByteArray, saltArray );
计算新字节数组的哈希值:
messageDigest = createObject( "java", "java.security.MessageDigest" );
messageDigest = messageDigest.getInstance( javaCast( "string", "SHA-512") );
hashedByteArray = messageDigest.digest( javacast("byte[]", mergedBytes) );
再次合并数组:
mergedBytes = mergeArrays( hashedByteArray, saltArray);
最后将二进制文件转换为base64并进行比较:
calculatedPayload = binaryEncode( javacast("byte[]", mergedBytes), "base64");
// check results
arePayloadsEqual = compare(calculatedPayload, payload_hash) eq 0;
WriteDump("arePayloadsEqual="& arePayloadsEqual);
WriteDump("calculatedPayload="& calculatedPayload);
WriteDump("payload_hash="& payload_hash);
注意:BinaryDecode/CharsetDecode
返回java数组。与CF数组不同,它们是不可变的(即不能更改)。所以handy addAll(..) trick在这里不起作用。
// merge immutable arrays the long way
function mergeArrays( array1, array2 ){
var i = 0;
var newArray = [];
for (i = 1; i <= arrayLen(arguments.array1); i++) {
arrayAppend(newArray, arguments.array1[i]);
}
for (i = 1; i <= arrayLen(arguments.array2); i++) {
arrayAppend(newArray, arguments.array2[i]);
}
return newArray;
}