HMAC与Cryptography API C / C ++

时间:2014-03-01 11:32:52

标签: c++ c cryptography cryptoapi

我正在使用http://msdn.microsoft.com/en-us/library/aa382379(v=vs.85).aspx中的Microsoft示例。它编译很好并且显示工作,返回结果:

48 f2 57 38 29 29 43 16 fd f4 db 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代码在某种程度上是正确的。这里发生了什么?

2 个答案:

答案 0 :(得分:4)

发布的C#代码和C代码链接(但未发布)做了不同的事情。因此输出也会不同。

WinCrypt代码执行以下操作:

  • 创建密钥字节的SHA1哈希
  • 使用RC4从结果哈希中导出会话密钥
  • 使用派生密钥
  • 初始化HMAC_SHA1摘要
  • 使用HMAC执行HMAC CryptHashData
  • 请求生成的哈希字节

C#代码执行以下操作:

  • 使用关键字节作为实际密钥创建HMAC_SHA1 (无派生)
  • 通过ComputeHash执行HMAC,返回生成的哈希摘要

换句话说,他们是不同的,因为他们做了不同的事情。哪一个是“正确的”取决于你想要做什么(问题中没有提到)。

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#代码匹配(省略,但请接受我的话或自己测试)。

答案 1 :(得分:1)

我认为使用CryptoAPI CryptCreateHash无法使用非派生密钥执行HMAC。

然而,可以使用Cryptography API:Next Generation(CNG)中的BCrypt方法集执行HMAC SHA1 / SHA256。有关示例,请参阅this question