Я пытаюсь создать цифровые подписи в Windows (из XP SP3, но в настоящее время тестирую Windows 7) с помощью CryptoAPI, который будет совместим со следующими командами openssl:
openssl dgst -sha256 -sign <parameters> (for signing)
openssl dgst -sha256 -verify <parameters> (for validation)
Я хочу использовать закрытый ключ из хранилища ключей Windows «MY» для подписи.
Мне удалось подписать файлы, используя алгоритм дайджеста SHA1, используя следующие функции CryptoAPI (для краткости опуская параметры):
CertOpenStore
CertFindCertificateInStore
CryptAcquireCertificatePrivateKey
CryptCreateHash (with CALG_SHA1)
CryptHashData
CryptSignHash
Сгенерированная подпись совместима с «openssl dgst -sha1 -verify» (после изменения порядка байтов).
Моя проблема: когда я пытаюсь использовать CALG_SHA_256 с CryptCreateHash, происходит сбой с ошибкой 80090008 (NTE_BAD_ALGID). Погуглив , я обнаружил, что мне нужно использовать определенный поставщик (PROV_RSA_AES) вместо поставщика по умолчанию. Поскольку у меня будет дескриптор поставщика, мне также потребуется заменить CryptAcquireCertificatePrivateKey на CryptGetUserKey. Поэтому я изменил свою программу, чтобы она выглядела так:
CryptAcquireContext (with PROV_RSA_AES)
CertOpenStore
CertFindCertificateInStore
CryptGetUserKey
CryptCreateHash (with CALG_SHA256)
CryptHashData
CryptSignHash
К сожалению, это не сработало, как ожидалось: CryptGetUserKey завершился с ошибкой 8009000D (NTE_NO_KEY). Если я удаляю вызов CryptGetUserKey, программа работает до CryptSignHash, что приводит к ошибке 80090016 (NTE_BAD_KEYSET). Я знаю, что набор ключей существует и отлично работает, так как я смог использовать его для подписи дайджеста SHA1.
Я попытался снова получить контекст с информацией из контекста сертификата, полученного из CertFindCertificateInStore: лучшее, что я мог сделать, это успешный вызов CryptGetUserKey, но CryptSignHash всегда завершался ошибкой с той же ошибкой.
Закрытый ключ, который я пытаюсь использовать, имеет длину 2048 бит, но я не ожидаю, что это будет проблемой, поскольку он работает с дайджестом SHA1. Я в недоумении, поэтому любое предложение будет очень кстати!