ColdFusion hmac()使用toBase64和binaryncode返回不同的值

ColdFusion hmac()使用toBase64和binaryncode返回不同的值,coldfusion,binary,hex,sha256,hmac,Coldfusion,Binary,Hex,Sha256,Hmac,我试图使用ColdFusion函数来计算HMAC值,使用binaryEncode(binaryObj,'Base64'),而不是因为不推荐使用该函数。它与toBase64()完美配合,但与binaryncode()不配合。这些文件的信息量不大。有人能帮我理解为什么我不能使用binarycode获得相同的值吗 据我所知,hmac()函数以十六进制格式返回结果binaryncode()需要一个二进制值,因此必须先将hmac()结果从十六进制转换为二进制,然后才能转换为base64 <cfset

我试图使用ColdFusion函数来计算HMAC值,使用
binaryEncode(binaryObj,'Base64')
,而不是因为不推荐使用该函数。它与
toBase64()
完美配合,但与
binaryncode()
不配合。这些文件的信息量不大。有人能帮我理解为什么我不能使用
binarycode
获得相同的值吗

据我所知,
hmac()
函数以十六进制格式返回结果
binaryncode()
需要一个二进制值,因此必须先将
hmac()
结果从十六进制转换为二进制,然后才能转换为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>

我注意到的一点是,使用
toBase64()
时,结果要长得多。我似乎不明白为什么不能使用
binaryEncode()
。但是,我想这样做,因为
toBase64()
正在被弃用。任何洞察都是值得赞赏的。谢谢

根据评论更新:

使用
ToBase64(Hmac(…)
不是将十六进制字符串转换为base64;-)的正确方法然而,听起来API需要的不是直接转换。如果是这样,只需执行
ToBase64(hmac(…)
代码正在执行的操作即可。ie将十六进制字符串解码为UTF8,并将其重新编码为base64:

matchingResult=binaryncode(字符集解码(hmacHex,“utf-8”),“base64”)


简短回答:

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

更长的回答:


toBase64:#toBase64(hmac(string,secretKey,'HMACSHA256'))#

实际上,这不是将十六进制转换为base64的正确方法

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

对于十六进制字符串,每个字节由两个字符表示。因此,二进制文件的大小将是原始字符串的一半。对于HMAC(HMACSHA256),生成的十六进制字符串长度为64个字符。所以二进制值应该是32字节。要获得正确的二进制值,字符串必须解码为十六进制:

ToBase64的问题在于它对字符串的解码不正确。它将输入视为UTF8,并单独解码字符串中的字符。所以二进制值是它应该大小的两倍。注意它是64字节,而不是32字节?这就是为什么最后一个字符串也更长的原因

UTF8 binary size = #arrayLen(charsetDecode(hmacHex, "utf-8"))# 
ToBase64 binary size = #arrayLen(binaryDecode(toBase64(hmacHex), "base64"))#
同样,这两种方法产生不同的结果,因为它们编码的值完全不同。然而,严格地说,只有第一种方法是正确的。要将十六进制字符串重新编码为base64,请使用:


谢谢你的回复。虽然我不能肯定地说什么是对的,什么是错的,但我可以说,使用带有CF的hmac()函数的binaryEncode/binaryDecode,结果本身似乎不正确。我认为ColdFusion中有些地方不正确,或者我让它从十六进制转换为二进制再转换为Base64的方式不正确。我们的支付处理器与数千家公司进行集成,并与toBase64()结果相匹配。另外,我们使用hash_hmac和base64_encode在PHP中设置它,它与CF的toBase64()结果匹配。这两件事让人觉得问题似乎出在binaryEncode/Decode w/cf的hmac()上。不过,我应该注意,我能够使用HMACSHA1获得匹配的hmac()签名值,使用HMACSHA256与我们的支付提供商和PHP的预期不符。支付处理器的单独规则以及它们所需要的是完全不同的故事;-)但是,这不是从十六进制转换为base64的正确方法。也就是说,如果这是他们的API所需要的,就按照我上面解释的做。将十六进制解码为UTF8,并将其重新编码为base64:
二进制编码(charsetDecode(hmacHex,“utf-8”),“base64”)
谢谢,您的答案非常有用!我从来没有想过支付处理程序本身会做得不正确,但这也许可以解释为什么我在这方面遇到了如此困难。添加charsetDecode(hmacHex,“utf-8”)实现了与我们的支付处理器相匹配的技巧。我现在可以避免使用toBase64(),因为它已经贬值了。非常感谢!这也许可以解释为什么我在这方面遇到了如此困难,这就是当你在一个不合逻辑的世界中尝试使用逻辑时会发生的情况;-)您最初的方法是将十六进制转换为base64的正确方法。然而,这正是他们的API。。好。。关于返回值的确切规则完全取决于他们。
original string length = #len(hmacHex)#
binary size = #arrayLen(binaryDecode(hmacHex, "hex"))#
UTF8 binary size = #arrayLen(charsetDecode(hmacHex, "utf-8"))# 
ToBase64 binary size = #arrayLen(binaryDecode(toBase64(hmacHex), "base64"))#
correctResult = binaryEncode(binaryDecode(hmacHex, "hex"), "base64")