3

次の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ダイジェストで機能するため、問題になるとは思われません。私は途方に暮れているので、どんな提案でも大歓迎です!

4

5 に答える 5

9

80090008ベースプロバイダーがSHA256、SHA384、SHA512をサポートしていないために発生します。CryptAcquireContext(hProv, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, 0);

于 2012-04-24T09:05:12.933 に答える
7

以前の回答のほとんどには、実際の回答の一部が含まれています。これを行う方法は、キーコンテナと「MicrosoftEnhanced RSA and AESCryptographicProvider」を使用するHCRYPTPROVを呼び出すことです。

CryptAcquireContext(&hCryptProv, <keyContainerName>, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, CRYPT_SILENT)

結果のhCryptProvを使用して、サポートされているすべてのSHA2(256、384、512)で作成されたハッシュに署名できます。

キーコンテナ名は、CertGetCertificateContextProperty()で引数CERT_KEY_PROV_INFO_PROP_IDを使用して取得できます。キーが証明書を介して取得される場合は、CryptGetProvParam()で引数PP_CONTAINERを使用して取得できます(たとえば、CryptAcquireCertificatePrivateで取得)。

この手法は、秘密鍵がエクスポートできない場合でも機能します。

于 2015-10-20T23:22:37.817 に答える
1

問題は、Windows上の証明書が、秘密鍵が格納されているプロバイダーを「認識」していることである可能性が最も高いです。証明書をインポートすると、キーが特定のプロバイダータイプ(おそらくPROV_RSA_FULL)になり、後で証明書を介してキーにアクセスしようとすると、おそらく同じプロバイダータイプになります。

おそらく、証明書に関連付けられたコンテキストを開く必要があります( CERT_KEY_PROV_HANDLE_PROP_IDオプションを指定したCertGetCertificateContextPropertyを参照してください)。そのハンドルを使用して、元のプロバイダーコンテキストからキーをエクスポートし、新しいPROV_RSA_AESコンテキストに再インポートしてみることができます(キーがエクスポート可能であると想定)。

于 2010-11-16T06:31:11.377 に答える
0

証明書を見つけたら、CertGetCertificateContextPropertywithを呼び出しCERT_KEY_PROV_INFO_PROP_IDて、キーを持つプロバイダーとコンテナーの名前を取得してみてください。CryptAcquireContextこれらの名前で呼び出してみてください。ただしPROV_RSA_AES、プロバイダータイプとして指定してください。

プロバイダー名を「MicrosoftEnhancedRSAand AES Cryptographic Provider」に置き換えてみることもできますが、プロバイダーが他のMicrosoftプロバイダーのいずれかでない限り、これは確実に機能しません。

于 2010-11-16T08:43:17.093 に答える
0

この投稿を見つける前に、最近同様の問題が発生しました。この投稿は問題の理解に役立ちますが、解決策は提供されませんでした。最後に、グーグルの助けを借りて、私は問題を解決しました。この質問は5年前に尋ねられましたが、他の人に役立つ場合に備えて、ここに解決策を書きます。

まず、私の問題について説明します。SSLサーバーとして機能するデバイスにOpenSSL 0.9.8を移植し、MicrosoftWindowsでSSLクライアントとして実行されるプログラムも提供しました。これもOpenSSLライブラリを使用します。クライアント証明書認証をサポートするこのクライアント/サーバーモデル。クライアントは、OpenSSLにRSA_methodを実装するMicrosoft Crypto-APIを呼び出して、証明書認証をサポートします。これまでのところ、 TLSv1.2をサポートするためにOpenSSLライブラリを0.9.8から1.0.2にアップグレードする前に非常に優れています。TLSv1.2を選択すると、クライアント証明書の認証は常に失敗します。デバッグ後、問題はクライアントプログラムのRSA_signメソッドにあることがわかりました。このメソッドは、ハッシュ結果に署名して、SSLクライアント検証メッセージで使用されるデジタル署名を取得します。署名操作は、を使用して計算されますCertFindCertificatePrivateKey/CryptCreateHash/CryptSetHashParam/CryptSignHashこの質問で説明されているAPI。エラーはCryptCreateHash呼び出しで発生しました。要求されたハッシュメソッドはSHA-384ですが、CertFindCertificatePrivateKeyによって取得されたhCryptoProvはCSP(Microsoft Enhanced Cryptographic Provider v1.0)に対応しており、SHA-2ハッシュメソッドをサポートしていません。

これは本当に退屈な説明です。あなたがまだ読み続けているなら、私はあなたも同様の問題に遭遇したと思います。私の解決策を紹介します。

私の最初の反応は、SSLネゴシエーションパラメータを調整してハッシュアルゴリズムをSHA-1にダウングレードすることでしたが、失敗しました。TLSv1.2ではSHA-2ハッシュが必須のようです。また、証明書の秘密鍵で暗号化して署名操作を実現しようとしましたが、これも失敗しました。Crypto-APIは、証明書の秘密鍵暗号化用のインターフェイスを提供しません(これはわかりませんが、見つかりませんでした)。2日間の結果のない試行の後、次のWebページを見つけました:http://www.componentspace.com/ Forums/Topic1578.aspx。まるでトンネルの終わりの光のようです。証明書はSHA-2をサポートしていないCSPとバインドされています。これを、SHA-2をサポートしているCSPに変換できれば、すべて問題ありません。リンク切れの場合は、ここに変換方法を貼り付けます。

openssl pkcs12 -export -in idp.pem -out new-idp.pfx -CSP "Microsoft Enhanced RSA and AES Cryptographic Provider"

Webページに記載されているように、.pfx証明書ファイルを再構築しました。証明書を再インポートしました。その後、問題は解決されます。

これがお役に立てば幸いです。:-)

于 2016-09-06T07:01:15.073 に答える