我有一个SHA1哈希,我需要签名。 CryptSignHash()方法需要一个HCRYPTHASH句柄进行签名。我创建它,因为我已经有了实际的哈希值,然后设置它:
CryptCreateHash(cryptoProvider, CALG_SHA1, 0, 0, &hash);
CryptSetHashParam(hash, HP_HASHVAL, hashBytes, 0);
hashBytes是一个20字节的数组。
然而问题是这个HCRYPTHASH句柄产生的签名是不正确的。我将问题追溯到CAPI实际上不使用我的hashBytes数组中的所有20个字节的事实。由于某种原因,它认为SHA1只有4个字节。
为了验证这一点,我写了这个小程序:
HCRYPTPROV cryptoProvider;
CryptAcquireContext(&cryptoProvider, NULL, NULL, PROV_RSA_FULL, 0);
HCRYPTHASH hash;
HCRYPTKEY keyForHash;
CryptCreateHash(cryptoProvider, CALG_SHA1, keyForHash, 0, &hash);
DWORD hashLength;
CryptGetHashParam(hash, HP_HASHSIZE, NULL, &hashLength, 0);
printf("hashLength: %d\n", hashLength);
这打印出hashLength:4!
任何人都可以解释我做错了什么或为什么Microsoft CAPI认为SHA1是4字节(32位)而不是20字节(160位)。
答案 0 :(得分:2)
您的代码中存在一个小错误。而不是
DWORD hashLength;
CryptGetHashParam(hash, HP_HASHSIZE, NULL, &hashLength, 0);
printf("hashLength: %d\n", hashLength);
你应该使用
DWORD hashLength, hashSize;
hashLength = sizeof(DWORD)
CryptGetHashParam(hash, HP_HASHSIZE, (PBYTE)&hashSize, &hashLength, 0);
printf("hashSize: %d\n", hashSize);
然后你将按预期收到20。
CryptSignHash
之后CryptSetHashParam
的使用情况也必须有效。请参阅http://msdn.microsoft.com/en-us/library/aa380270(VS.85).aspx CryptSetHashParam
函数说明末尾的注释。我想你在检索签名结果时犯了与CryptGetHashParam(..., HP_HASHSIZE, ...)
相同的错误。将您的代码与CryptSignHash
函数http://msdn.microsoft.com/en-us/library/aa380280(VS.85).aspx的说明中的代码进行比较。
答案 1 :(得分:1)
我认为你不能以这种方式使用CryptCreateHash
。来自MSDN:
“CryptCreateHash功能 启动一个流的散列 数据“。
换句话说,看起来你不能以空的方式实例化哈希上下文(然后让它对你的输入数据进行哈希)。
你目前如何获得哈希 - 一个字节数组?如果是这样,你可能只想签署该数组;我会考虑CryptSignMessage
或CryptSignMessageWithKey
来完成这项工作。
(我猜,但你所看到的可能是由于在哈希上下文完成某些工作之后,输出哈希长度没有被设置。)