18

ローカルマシンのルート証明書ストアに秘密鍵を含む新しいCA証明書を挿入する際に問題が発生しました。

これが起こることです:

//This doesn't help either.
new StorePermission (PermissionState.Unrestricted) { Flags = StorePermissionFlags.AddToStore }.Assert();
var store = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
privkey.PersistKeyInCsp = true;
//This shouldn't be necessary doesn't make a difference what so ever.
RSACryptoServiceProvider.UseMachineKeyStore = true;
cert.PrivateKey = privkey;
store.Open (OpenFlags.MaxAllowed);
store.Add (cert);
store.Close ();

証明書が挿入され、すべてがダンディに見えます:(参照してください!)秘密鍵があると書かれていることに注意してください

注:それは秘密鍵を持っていると言っています。

つまり、 FindPrivateKeyでそれを見つけることができると言うでしょう

C:\Users\Administrator\Desktop>FindPrivateKey.exe Root LocalMachine -t "54 11 b1 f4 31 99 19 d3 5a f0 5f 01 95 fc aa 6f 71 12 13 eb"
FindPrivateKey failed for the following reason:
Unable to obtain private key file name

Use /? option for help 

それはかわいいです....しかし、それは間違っています!(2匹の愚かな犬の参照)

そして、証明書のエクスポートダイアログは私にこの非常に細かいメッセージを与えます: 代替テキスト

このコードは、このスニペットを使用して管理者になりすましているときに実行されます。ここをクリックしてください

なぜ知りたいのですか?

(Windows Server 2008R2およびWindows7でテスト済み)

いまいましい!

v3.5にコンパイルすると動作します!!!!

何をすべきか?

4

6 に答える 6

11

私はまったく同じ問題を抱えていましたが、解決策は本当に簡単でした。私がしなければならなかったのは合格することだけでした

X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet

X509Certificate2 の ctor に。DotNetUtilities を使用して bouncycastle 証明書を .net 証明書に変換していますが、ヘルパー メソッドは ( MachineKeySet + PersistKeySet ではなく) DefaultKeySet を使用して .net 証明書を作成します。

そして、秘密鍵を次のように配置します。

var cspParams = new CspParameters
{
      KeyContainerName = Guid.NewGuid().ToString(),
      KeyNumber = (int)KeyNumber.Exchange,
      Flags = CspProviderFlags.UseMachineKeyStore
};

var rsaProvider = new RSACryptoServiceProvider(cspParams);

これが役立つことを願っています。

于 2011-06-23T14:20:20.160 に答える
10

少し別の方法でキーをインポートする必要があるようです。例については、 http://support.microsoft.com/kb/950090を参照してください。

さらに、秘密鍵をに保存するのは良くないと思いますUseMachineKeyStore。ほとんどの場合、一部のユーザーのマイ ストアにある秘密キーを使用して証明書をインポートし、秘密キーを使用せずにルートのみの証明書をインポートする必要があります。

プライベート キーをマシン キー ストアに保存する必要がある場合は、少なくとも、すべてのユーザーからではなく、選択した一部のユーザーに対してのみキーを読み取れるように保護する必要があります。キー コンテナーは、NTFS の他のファイルと同様にセキュリティ記述子を持つ、ファイル システム内の単なるファイルです (ディレクトリ "%ALLUSERSPROFILE%\Microsoft\Crypto\Keys" 内のファイルを参照)。CspKeyContainerInfo.CryptoKeySecurityファイルのセキュリティ記述子を変更するには、 property や などAddAccessRuleを使用できますRemoveAccessRule

更新: まず、長い回答で申し訳ありません。

あなたのプログラム コードを 2 つの部分に分けることができます。最初の部分では、CA 証明書として使用できる自己署名証明書を生成し、それをrootcert.pfxファイルとして保存します。2 番目の部分では、証明書をインポートしますが、rootcert.pfxRSACryptoServiceProviderを使用する代わりに、以前に作成されたキーのプロパティが入力されたものを使用します。

コードの 2 番目の部分をより標準的で単純なコードに置き換えることをお勧めします: http://support.microsoft.com/kb/950090で説明されているように、 rootcert.pfxから秘密キーを使用して証明書をインポートします。それは非常にうまく機能します。

私は BouncyCastle を使用していないため、コードの最初の部分にコメントすることはできませんでしたが、一般的に、コードで行うことは、Windows SDKのMakeCert.exeユーティリティに関しても行うことができます。次のようにすることができます

MakeCert.exe -pe -ss MY -a sha1 -cy authority -len 2048 -m 120 -r -# 1
             -n "CN=Some Root CA, C=NL, OU=BleedingEdge, ST=Somewhere, L=Somelane"

次に、証明書スナップイン (mmc.exe 用) に関して、秘密キーの有無にかかわらず証明書をエクスポートできます。上記の例では、一部の特別な EKU に対して CA を制限していないため、制限なしで使用できますが、制限が必要な場合は、MakeCert.exeにパラメーターを追加するだけです。MakeCert.exe を使用して、CA 証明書で署名された他の証明書を作成することもできます。したがって、MakeCert.exe のみに関して小さな PKI を作成できます。

証明書の作成は、実際にはコードの別の部分であるように思えます。あなたの主な問題は2番目の部分にあります。

CA 証明書をインポートする場合は、いくつかの重要なことを考慮する必要があります。

  • 組織のすべての (または多数の) コンピュータにインポートする必要がありますが、秘密鍵なしで証明書をインポートする必要Rootがあります。次の点でこれを行うことができますAuthRootlocalMachine

CertMgr.exe -add -c CA.cer -s -r localMachine AuthRoot

  • 1台のコンピューター上のコンピューターに秘密キーを含むCA 証明書をインポートする必要があります。これは、他の証明書を発行するユーザー(CA の秘密キーを使用して新しい証明書に署名するユーザー) に対してのみ行う必要があります。CurrentUserのMy certificate store に証明書をインポートするために 1 回使用します。したがって、コンピューター上のコードは次のようになります

続く:

// import PFX
X509Certificate2 cert = new X509Certificate2 (@"c:\Oleg\rootcert.pfx", "password",
    X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);
// save certificate and private key
X509Store storeMy = new X509Store (StoreName.My, StoreLocation.CurrentUser);
storeMy.Open (OpenFlags.ReadWrite);
storeMy.Add (cert);

// get certificate without private key
// one can import certificate from rootcert.cer instead
byte[] certBlobWithoutPrivateKey = cert.Export (X509ContentType.Cert);
// save pure certificate in Root of the local machine
X509Certificate2 certWithoutPrivateKey = new X509Certificate2 (certBlobWithoutPrivateKey);
X509Store storeRoot = new X509Store (StoreName.Root, StoreLocation.LocalMachine);
storeRoot.Open (OpenFlags.ReadWrite);
storeRoot.Add (certWithoutPrivateKey);

StoreName.My別の値に変更してもコードは機能しますがStoreLocation.CurrentUser、これを行うことはお勧めしません。

一般に、.NET コードでの証明書のインポートは少し奇妙に見え、内部で何が行われるかを示していません。Windowsは、証明書が保存されるCSP および証明書ストアに関して秘密キー (正確にはキー ペア) が保存されるキー コンテナーのみを認識します ( http://msdn.microsoft.com/en-us/library/bb204781を参照)。店舗の場所に関する.aspx )。キー コンテナに関する情報を証明書ストアに保存できるようにするために、Microsoft は証明書拡張プロパティという名前を導入しました。、、、などの.NETプロパティで使用する場合X509Certificate2ThumbprintFriendlyNameHasPrivateKeyArchivedなど、証明書の拡張プロパティを操作します。そのため、CA 証明書を 2 回インポートすることをお勧めします。1 つは証明書の拡張プロパティを設定するRootかどうかに関係AuthRoot なく、もう 1 つは秘密鍵を含むキー コンテナーの場所に関する情報を設定して保存ます ( )。さらに、使用後に直接秘密鍵を削除し、本当に使用する必要がある場合にのみインポートし、永久に保持しないことを検討できます。これらすべては、より良いセキュリティを確保するために重要です。CERT_KEY_PROV_INFO_PROP_ID MyCERT_KEY_PROV_INFO_PROP_ID

于 2010-09-05T11:15:38.060 に答える
2

この問題が発生しました。FindPrivateKey ツールを実行しているユーザーでさえ、キーにアクセスできないようです。そのため、「秘密キー ファイル名を取得できません」というメッセージが表示されます。ツールを LocalSystem プロセスとして実行できます。

詳細はこちら:

http://www.itsolutionbraindumps.com/2011/02/finding-private-key-for-your.html

ディンコ

于 2011-02-11T16:45:05.883 に答える
0

通常、ルートの証明書には、管理する秘密鍵がありません。Web リクエストでキーを関連付ける場合は、My フォルダーにインポートする必要があります。クライアント証明書のチェーンがあるところに TLS/SSL 例外があります。証明書のすべてのチェーンを My ストアに保存すると、その例外がなくなりました。問題がユーザー アカウントにある場合。証明書を保存するユーティリティは現在のユーザー アカウントを使用し、実際のアプリケーションはシステム アカウントで実行されます。

于 2016-08-22T16:29:04.013 に答える
0

new X509Certificate2(localPFXPath, inputPass, X509KeyStorageFlags.MachineKeySet & X509KeyStorageFlags.PersistKeySet); | の代わりに & を使用 私のために働いた。

于 2016-03-10T20:30:59.943 に答える
0

基本的な問題は、.NET 証明書 API が C++ advapi32 証明書マネージャー API の単なるラッパーであるため、この API に渡されるすべてのオプションを指定する必要がないことです。証明書ストアとキーの永続化。要するに、「<em>UseMachineStore」オプションを CspProviderFlags に渡す必要があり、これがCAPI.CRYPT_MACHINE_KEYSETに渡されます。これは、キーが実際に永続化されるかどうかを決定する小さな男です。X509KeyStorageFlags.PersistKeySetMachineKeySetExportableを設定しても、このオプションが設定されない理由はいくつかあるようです. これらのオプションはすべて、愚かなキーが C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys\ フォルダーにある限り有効です。インポート時に CRYPT_MACHINE_KEYSET が設定されていない場合、証明書ハンドルが GC によって破棄されるとすぐに advapi32 がキーを吹き飛ばします。

解決策: 証明書をパーソナル マシン ストアにインポートする前に、信頼されたルートに証明書を追加します。CAPI2 からログを読み取ると、実際には、証明書が「インポート」されるたびに「X509 オブジェクト」への 2 つの呼び出しが表示されます。一方には常に<Flags value="20" CRYPT_MACHINE_KEYSET="true"/>, (必要なもの) がありますが、もう一方には「Verify Chain Policy」がエラーを返さない限り、ありません。したがって、advapi32が証明書の「有効性」をチェックしているように見え、X509Certificate2 によって飲み込まれる例外を返します (そのコードに空の catch ブロックがいくつあるかが気に入っています。) または advapi32 が、信頼されていない証明書のキーを保持しないことを一方的に決定しただけです。(ちなみに、これは 2008 年から 20012 年の間の動作の変更であると思われますが、それを証明していません。) これを回避するために、コードに If-check を追加して、Issuer がサブジェクト (これは自己署名証明書です) 次に、その証明書をルートに追加してから、My.

    if (certificate.Issuer.Equals(certificate.Subject))
    {
        using (X509Store store = new X509Store(StoreName.Root, StoreLocation.LocalMachine)) { 
            store.Open(OpenFlags.ReadWrite);
            store.Add(certificate);
            store.Close();
        }
    }

    using (X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine)){ 
        store.Open(OpenFlags.ReadWrite);
        store.Add(certificate);
        store.Close();
    }

注:サブジェクト キー識別子が含まれていない証明書を使用する場合、これは不要であることがわかりました。SKI を渡すのではなく実際に SKI を生成するように API をトリガーすると、どういうわけか、魔法の CRYPT_MACHINE_KEYSET フラグを advapi32 に渡す条件がトリガーされます。

于 2017-10-26T17:17:07.153 に答える