4

我有一个 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 位)。

4

2 回答 2

3

您的代码中有一个小错误。代替

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 个。

CryptSignHashafter的用法CryptSetHashParam也必须有效。请参阅http://msdn.microsoft.com/en-us/library/aa380270(VS.85).aspxCryptSetHashParam功能描述末尾的备注。我想你只是在检索签名结果期间犯了同样的错误。将您的代码与函数http://msdn.microsoft.com/en-us/library/aa380280(VS.85).aspx描述中的代码进行比较。CryptGetHashParam(..., HP_HASHSIZE, ...)CryptSignHash

于 2010-06-08T19:34:51.013 回答
1

我认为您不能CryptCreateHash以这种方式使用。来自MSDN

“CryptCreateHash 函数启动数据流的散列。”

换句话说,看起来您无法以除空之外的任何方式实例化哈希上下文(然后通过让它对您的输入数据进行哈希处理)。

您目前如何拥有哈希 - 字节数组?如果是这样,您可能只想签署该数组;我会调查CryptSignMessageCryptSignMessageWithKey可能会做这项工作。

(我猜,但您所看到的可能是在哈希上下文完成一些工作之后才设置输出哈希长度来解释。)

于 2010-05-28T11:26:01.017 回答