次のopensslコマンドと互換性のあるCryptoAPIを使用して、Windows(XP SP3からですが、現在Windows 7でテスト中)でデジタル署名を生成しようとしています。
openssl dgst -sha256 -sign <parameters> (for signing)
openssl dgst -sha256 -verify <parameters> (for validation)
署名には、Windowsの「MY」キーストアの秘密鍵を使用したいと思います。
次のCryptoAPI関数(簡潔にするためにパラメーターを省略)を使用して、SHA1ダイジェストアルゴリズムを使用してファイルに署名することができました。
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ダイジェストで機能するため、問題になるとは思われません。私は途方に暮れているので、どんな提案でも大歓迎です!