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

时间:2016-10-03 22:25:49

标签: coldfusion binary hex sha256 hmac

我正在尝试使用ColdFusion的hmac()函数来计算HMAC值,使用binaryEncode(binaryObj,' Base64')而不是toBase64,因为toBase64正在折旧。它与toBase64()完美配合,但不与binaryEncode()配合使用。这些文档的信息量不大。有人能帮助我理解为什么我不能使用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被折旧。任何见解都非常感谢。谢谢!

1 个答案:

答案 0 :(得分: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>

实际上是将hex转换为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,请使用binaryEncode/binaryDecode

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