2014-03-01 29 views
1

我使用的是來自http://msdn.microsoft.com/en-us/library/aa382379(v=vs.85).aspx的Microsoft示例。它編譯細並出現工作,返回結果:HMAC with Cryptography API C/C++

48 F2 57 38 29 29 43 16 FD F4分貝58 31 E1 0C 74 48 8E D4 E2

然而,當我用下面的C#代碼運行相同的計算,我得到不同的散列?

4C-2D-E3-61-BA-89-58-55-8D-E3-D0-49-ED-1F-B5-C1-15-65-6E-65

 HMAC hashMaker = new HMACSHA1(new byte[]{0x70,0x61,0x73,0x73,0x77,0x6F,0x72,0x64}); 
     byte[] hash = hashMaker.ComputeHash(new byte[] {0x6D,0x65,0x73,0x73,0x61,0x67,0x65}); 
     string hashStr = BitConverter.ToString(hash); 

我擔心示例C代碼在某些方面是正確的。這裏發生了什麼?

回答

4

張貼的C#代碼和C代碼鏈接(但不是張貼)做不同的事情。因此輸出也會有所不同。

的WinCrypt代碼執行下列:

  • 創建密鑰字節
  • 使用RC4
  • 使用推導的初始化HMAC_SHA1消化派生從所得到的散列的會話密鑰的SHA1哈希鍵
  • 使用HMAC執行HMAC CryptHashData
  • 請求產生的散列字節

C#代碼執行以下步驟:

  • 使用密鑰字節作爲實際鍵(無偏差)
  • 執行經由ComputeHash的HMAC創建HMAC_SHA1,返回所得到的散列digest

換句話說,它們是不同的,因爲它們在做不同的事情。哪一個是「正確」取決於你想要做什麼(問題中沒有提到)。

OpenSSL的等效於C#代碼

unsigned char key[] = { 0x70,0x61,0x73,0x73,0x77,0x6F,0x72,0x64 }; 
unsigned char bytes[] = { 0x6D,0x65,0x73,0x73,0x61,0x67,0x65 }; 
unsigned char md[32] = {0}; 
unsigned int md_len = (int)sizeof(md); 

HMAC_CTX ctx; 
HMAC_CTX_init(&ctx); 
HMAC_Init(&ctx, key, (int)sizeof(key), EVP_sha1()); 
HMAC_Update(&ctx, bytes, sizeof(bytes)); 
HMAC_Final(&ctx, md, &md_len); 

將所得消化md C#代碼分別匹配(省略,但相信我的話它或測試它自己)。

+0

非常感謝您花時間回答問題。我試圖直接推進HMAC sha1,沒有派生。我確實想知道爲什麼會有RC4的東西,並不認爲這是HAMC的一部分。 CryptCreateHash需要密碼與CBC的分組密碼,這看起來是不可能的。 OpenSSL示例看起來更簡潔明瞭!我有點C++新手,所以可能會困難的連接等wincrypt很容易,因爲它只是在VS中,但API真的很難。 –

+0

我知道這是一箇舊帖子,但想說這個答案感謝。我花了很長時間試圖調試爲什麼我的Wincrypt HMAC實現不起作用。最終,我訴諸於[this](基於bcrypt的實現)(http://stackoverflow.com/questions/22147895/is-it-possible-to-do-a-hmac-with-wincrypt)。儘管如此,我還是非常迷戀,不讓這些事情發生。我調查了爲什麼我的'wincrypt'方法不起作用,並且懷疑它是MSDN示例中的'RC4'步驟,這篇文章讓我放心! –

1

我相信不可能使用CryptoAPI CryptCreateHash執行帶有非派生鍵的HMAC。

但是,可以使用加密API:下一代(CNG)中的BCrypt方法來執行HMAC SHA1/SHA256。一個例子見this question