Using SHA1 with Microsoft CAPI

I have a SHA1 hash and I need to sign it. The CryptSignHash () method requires a HCRYPTHASH handle to write. I create it, and since I have the actual value of the hash code, install it:

CryptCreateHash(cryptoProvider, CALG_SHA1, 0, 0, &hash); CryptSetHashParam(hash, HP_HASHVAL, hashBytes, 0); 

hashBytes is an array of 20 bytes.

However, the problem is that the signature created using this HCRYPTHASH manuscript is incorrect. I traced the problem to the point that CAPI does not actually use all 20 bytes from my hashBytes array. For some reason, he believes that SHA1 is only 4 bytes.

To test this, I wrote this little program:

 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); 

And that prints hashLength: 4!

Can someone explain what I'm doing wrong or why Microsoft CAPI thinks that SHA1 is 4 bytes (32 bits) instead of 20 bytes (160 bits).

+4
source share
2 answers

There is a small error in your code. Instead

 DWORD hashLength; CryptGetHashParam(hash, HP_HASHSIZE, NULL, &hashLength, 0); printf("hashLength: %d\n", hashLength); 

you should use

 DWORD hashLength, hashSize; hashLength = sizeof(DWORD) CryptGetHashParam(hash, HP_HASHSIZE, (PBYTE)&hashSize, &hashLength, 0); printf("hashSize: %d\n", hashSize); 

then you will get 20 as expected.

Using CryptSignHash after CryptSetHashParam should also work. See the note at the end of the CryptSetHashParam function CryptSetHashParam at http://msdn.microsoft.com/en-us/library/aa380270(VS.85).aspx . I suppose you just made the same mistake as with CryptGetHashParam(..., HP_HASHSIZE, ...) when receiving the signing result. Compare your code with the code from the description of the CryptSignHash function http://msdn.microsoft.com/en-us/library/aa380280(VS.85).aspx .

+2
source

I do not think you can use CryptCreateHash this way. From MSDN :

"The CryptCreateHash function initiates hashing a stream of data."

In other words, it looks like you cannot create a hash context in any other way than empty (and then using the hash data for input).

How do you have the hash now - an array of bytes? If so, you probably just want to sign this array; I would look in CryptSignMessage or CryptSignMessageWithKey , completing the task as soon as possible.

(I suppose, but what you see can be explained by the fact that the length of the hash output is not configurable until the hash context does some work.)

+1
source

Source: https://habr.com/ru/post/1311193/


All Articles