2016-10-03 100 views
1

我尝试使用ColdFusion的hmac()函数来计算使用binaryEncode(binaryObj,'Base64')而不是toBase64的HMAC值,因为toBase64正在折旧。它适用于toBase64(),但不适用于binaryEncode()。文档不是很丰富。有人可以帮助我理解为什么我不能使用binaryEncode获得相同的值吗?ColdFusion hmac()返回不同的值toBase64和binaryEncode

据我所知,hmac()函数以十六进制格式返回结果。 BinaryEncode()需要一个二进制值,因此必须先将hmac()结果从Hex转换为Binary,以便它可以从Binary转换为Base64。

<cfset string = "1234567890" /> 
<cfset secretKey = "abcdefghijklmnopqrstuvwxyz" /> 
<!--- Get Hex results from HMAC() ---> 
<cfset hmacHex = hmac(string,secretKey,'HMACSHA256') /> 
<!--- Decode the binary value from hex ---> 
<cfset hmacAsBinary = binaryDecode(hmacHex,'hex') /> 
<!--- Convert binary object to Base64 ---> 
<cfset hmacBase64 = binaryEncode(hmacAsBinary, 'base64') /> 
<cfoutput> 
    <!--- incorrect hmac signature ---> 
    hmacBase64: #hmacBase64#<br> 
    <!--- correct hmac signature ---> 
    toBase64: #toBase64(hmac(string,secretKey,'HMACSHA256'))#<br> 
</cfoutput> 

的结果是:

hmacBase64: VEVGNnqg9b0eURaDCsA4yIOz5c+QtoJqIPInEZOuRm4= 
toBase64: NTQ0NTQ2MzY3QUEwRjVCRDFFNTExNjgzMEFDMDM4Qzg4M0IzRTVDRjkwQjY4MjZBMjBGMjI3MTE5M0FFNDY2RQ== 

有一件事我注意到的是结果是更长的使用toBase64时。我似乎无法弄清楚为什么我不能使用binaryEncode。我想自从toBase64被折旧。任何见解都非常感谢。谢谢!

回答

3

更新基于评论:

那么使用ToBase64(Hmac(...))为十六进制字符串转换为Base64 ;-)但是,它听起来就像是API的正确方法需要比直接转换其他的东西。如果是这样,只需执行ToBase64(hmac(...))代码正在做的事情。即解码十六进制字符串作为UTF8和重新编码它为base64:

matchingResult = binaryEncode(charsetDecode(hmacHex, "utf-8"), "base64")


短的答案:

这两种方法的编码完全不同的值。这就是结果不匹配的原因。将十六进制字符串转换为base64的正确方法是使用BinaryEncode/Decode()

较长的答案:

<!--- correct hmac signature --->
toBase64: #toBase64(hmac(string,secretKey,'HMACSHA256'))#<br>

其实是为十六进制转换为Base64的正确方法。

十六进制和Base64只是表示二进制值值的不同方式。为了得到相同的结果,这两种方法需要以相同的二进制开始。在这种情况下,实际上编码的是完全不同的值。因此结果的差异。

对于十六进制字符串,每个字节由两个字符表示。所以二进制将是一半原始字符串的大小。在HMAC(HMACSHA256)的情况下,得到的十六进制字符串长度为64个字符。所以二进制的值应该是32个字节。为了获得正确的二进制值,必须将字符串解码为十六进制

original string length = #len(hmacHex)# 
binary size = #arrayLen(binaryDecode(hmacHex, "hex"))# 

与ToBase64的问题是,它的字符串译码错误。它将输入视为UTF8,并将字符串中的字符分别解码为。所以二进制值的大小应该是它的两倍。注意它是64个字节,而不是32个?这就是为什么最后的字符串更长。

UTF8 binary size = #arrayLen(charsetDecode(hmacHex, "utf-8"))# 
ToBase64 binary size = #arrayLen(binaryDecode(toBase64(hmacHex), "base64"))# 

再次,这两种方法产生不同的结果,因为它们编码的是完全不同的值。但严格来说,只有第一种方法是正确的。要将base64字符串重新编码为base64,请使用binaryEncode/binaryDecode

correctResult = binaryEncode(binaryDecode(hmacHex, "hex"), "base64") 
+0

感谢您的回应Leigh。虽然我不能确定是对还是错,但我可以说结果本身似乎使用了binaryEncode/binaryDecode和CF的hmac()函数。我认为ColdFusion中有些东西不正确,或者我将它从Hex转换为Binary转换为Base64。我们的支付处理器可与数千家公司进行集成,并与toBase64()结果相匹配。另外,我们使用hash_hmac和base64_encode在PHP中设置它,并且它匹配CF的toBase64()结果。这两件事看起来像是用binaryEncode/Decode w/cf的hmac()解决问题。 – billvsd

+0

我应该注意到,我能够使用HMACSHA1获得匹配的hmac()签名值,但是,使用HMACSHA256与我们的支付提供程序和PHP不符。 – billvsd

+1

那么支付处理器的个别规则和他们所要求的是完全不同的故事;-)但是,这不是*将十六进制转换为base64的正确方法。也就是说,如果这就是他们的API所要求的,那就按照我上面所解释的那样做。将十六进制解码为UTF8,并将其重新编码为base64:'binaryEncode(charsetDecode(hmacHex,“utf-8”),“base64”)' – Leigh