2016-04-12 237 views
4

我需要通過使用SHA256哈希函數來計算HMAC。我有一個以base64格式編碼的密鑰。還有一個在線工具可以正確計算HMAC(已驗證)。 http://www.freeformatter.com/hmac-generator.html 我寫了下面的代碼片段:C#中HMAC SHA256哈希計算

var signatureHashHexExpected = "559bd871bfd21ab76ad44513ed5d65774f9954d3232ab68dab1806163f806447"; 
var signature = "123456:some-string:2016-04-12T12:44:16Z"; 
var key = "AgQGCAoMDhASFAIEBggKDA4QEhQCBAYICgwOEBIUAgQ="; 

var shaKeyBytes = Convert.FromBase64String(key); 
using (var shaAlgorithm = new System.Security.Cryptography.HMACSHA256(shaKeyBytes)) 
{ 
    var signatureBytes = System.Text.Encoding.UTF8.GetBytes(signature); 
    var signatureHashBytes = shaAlgorithm.ComputeHash(signatureBytes); 
    var signatureHashHex = string.Concat(Array.ConvertAll(signatureHashBytes, b => b.ToString("X2"))).ToLower(); 

    System.Diagnostics.Debug.Assert(signatureHashHex == signatureHashHexExpected); 
} 

問題: 我的代碼不會產生正確的HMAC。我通過使用不同的在線工具和替代C#實現來驗證不同的步驟。只有從base64轉換未被確認。我錯過了什麼?

UPDATE:通過我的代碼 計算signatureHashHex是「a40e0477a02de1d134a5c55e4befa55d6fca8e29e0aa0a0d8acf7a4370208efc」

答: 的問題是由誤導性陳述文檔的關鍵在Base64格式設置造成的。見接受的答案:

var shaKeyBytes = System.Text.Encoding.UTF8.GetBytes(key); 
+0

你確定簽名是用UTF8編碼的嗎? –

+0

你試過這個:http://stackoverflow.com/q/33419006/479156 – Ivar

+0

不,但我嘗試了許多不同的編碼,結果相同。 – Kalitsov

回答

5

你的結果是正確的,所不同的是,因爲你鏈接到工具確實解碼Base64編碼的鍵值,將其視爲一系列字符。

E.g.要複製它的結果把你的密鑰字符串:

var shaKeyBytes = System.Text.Encoding.UTF8.GetBytes("AgQGCAoMDhASFAIEBggKDA4QEhQCBAYICgwOEBIUAgQ="); 

其中產量

559bd871bfd21ab76ad44513ed5d65774f9954d3232ab68dab1806163f806447 

(這顯然不是做正確的方式)

+0

麻煩解釋,爲什麼'GetBytes(...)'是「明顯錯誤的」?如果我的keyphrase是「This_is_my_secret_keyphrase」? – derpirscher

+0

由於Base64字符串是應該使用的字節及其那些字節(解碼後)的編碼序列,而不是字符串本身。你不要點新的椅子,然後坐在箱子上。 (''This_is_my_secret_keyphrase「'不是Base64) –

+1

一個簡單的字符串也是一系列編碼的字節。這只是一個解釋問題。密碼短語存儲的格式完全不相關,只要它可以轉換爲用於加密/解密的正確字節向量即可。 'Convert.FromBase64String(「VGhpc19pc19teV9zZWNyZXRfa2V5cGhyYXNl」)'和'System.Text.Encoding.UTF8.GetBytes(「This_is_my_secret_keyphrase」)''有什麼區別?必須確保雙方在相同的輸入上使用相同的方法。我不記得要求密鑰是base64字符串。 – derpirscher

0

HMAC:這是一個消息認證碼。它用於驗證發送者的數據完整性,它是一種前向唯一算法。它對發送者和接收者都知道的共享密鑰都有效。在生成哈希值之前,我們必須對密鑰和消息進行編碼。我們可以使用編碼UTF8ASCIIEncoding中的任何一個。

UTF8編碼:

var signature = "123456:some-string:2016-04-12T12:44:16Z"; 
var key = "AgQGCAoMDhASFAIEBggKDA4QEhQCBAYICgwOEBIUAgQ="; 


var signatureBytes = System.Text.Encoding.UTF8.GetBytes(signature); 
var shaKeyBytes = System.Text.Encoding.UTF8.GetBytes(key); 

ASCIIEncoding編碼:

var signature = "123456:some-string:2016-04-12T12:44:16Z"; 
var key = "AgQGCAoMDhASFAIEBggKDA4QEhQCBAYICgwOEBIUAgQ="; 

var signatureBytes = System.Text.ASCIIEncoding.GetBytes(signature); 
var shaKeyBytes = System.Text.ASCIIEncoding.GetBytes(key); 

現在,我們可以在上面的代碼中使用此編碼的消息和密鑰。