2016-10-03 103 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