少し別の方法でキーをインポートする必要があるようです。例については、 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
があります。次の点でこれを行うことができますAuthRoot
localMachine
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プロパティで使用する場合X509Certificate2
Thumbprint
FriendlyName
HasPrivateKey
Archived
など、証明書の拡張プロパティを操作します。そのため、CA 証明書を 2 回インポートすることをお勧めします。1 つは証明書の拡張プロパティを設定するRoot
かどうかに関係AuthRoot
なく、もう 1 つは秘密鍵を含むキー コンテナーの場所に関する情報を設定して保存します ( )。さらに、使用後に直接秘密鍵を削除し、本当に使用する必要がある場合にのみインポートし、永久に保持しないことを検討できます。これらすべては、より良いセキュリティを確保するために重要です。CERT_KEY_PROV_INFO_PROP_ID
My
CERT_KEY_PROV_INFO_PROP_ID