与Microsoft CAPI一起使用SHA1

与Microsoft CAPI一起使用SHA1,c,cryptoapi,C,Cryptoapi,我有一个SHA1哈希,我需要签名。CryptSignHash()方法需要HCRYPTHASH句柄进行签名。我创建了它,因为我已经有了实际的散列值,所以设置它: CryptCreateHash(cryptoProvider, CALG_SHA1, 0, 0, &hash); CryptSetHashParam(hash, HP_HASHVAL, hashBytes, 0); hashBytes是一个20字节的数组 但是,问题是,此HCRYPTHASH句柄生成的签名不正确。我将问题归结为这

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

我认为你不能这样使用
CryptCreateHash
。发件人:

“CryptCreateHash函数 启动数据流的哈希 数据。”

换句话说,看起来除了空(然后让它散列您的输入数据)之外,您无法以任何方式实例化散列上下文

目前如何使用哈希-字节数组?如果是这样,您可能只想对该数组进行签名;我会研究
CryptSignMessage
CryptSignMessageWithKey
来完成这项工作


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

代码中有一个小错误。而不是

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个预期

CryptSetHashParam
之后使用
CryptSignHash
也必须起作用。请参阅位于的
CryptSetHashParam
函数描述末尾的备注。我想您刚才在检索签名结果时犯了与CryptGetHashParam(…,HP_HASHSIZE,…)相同的错误。将您的代码与
CryptSignHash
函数描述中的代码进行比较