Использование SHA1 с Microsoft CAPI - PullRequest
4 голосов
/ 28 мая 2010

У меня есть хэш SHA1, и мне нужно его подписать. Метод CryptSignHash () требует дескриптор HCRYPTHASH для подписи. Я создаю его и, поскольку у меня уже есть фактическое значение хеш-функции, установите его:

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

hashBytes - это массив из 20 байтов.

Однако проблема в том, что подпись, созданная этим дескриптором HCRYPTHASH, неверна. Я проследил проблему до того факта, что CAPI фактически не использует все 20 байтов из моего массива hashBytes. По некоторым причинам он считает, что 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 бит).

Ответы [ 2 ]

2 голосов
/ 08 июня 2010

В вашем коде небольшая ошибка. Вместо

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 также должно работать. См. Примечание в конце описания функции CryptSetHashParam на http://msdn.microsoft.com/en-us/library/aa380270(VS.85).aspx. Полагаю, вы только что совершили ту же ошибку, что и CryptGetHashParam(..., HP_HASHSIZE, ...) во время получения результата подписания. Сравните ваш код с кодом из описания CryptSignHash функция http://msdn.microsoft.com/en-us/library/aa380280(VS.85).aspx.

1 голос
/ 28 мая 2010

Я не думаю, что вы можете использовать CryptCreateHash таким образом.From MSDN :

"Функция CryptCreateHash инициирует хеширование потока данных."

Другими словами, похоже, что вы можетене создавать экземпляр хеш-контекста, кроме как пустым (а затем хэшировать его входные данные).

Откуда у вас хеш в настоящее время - байтовый массив?Если это так, вы, вероятно, просто хотите подписать этот массив;Я бы посмотрел на CryptSignMessage или CryptSignMessageWithKey как наиболее вероятные для этой работы.

(я предполагаю, но то, что вы видите, может объясняться тем, что длина выходного хеша не устанавливается допосле того, как контекст хеша проделал некоторую работу.)

...