2013-05-07 4 views
9

生成された証明書をバイト配列との間でエクスポートしてインポートする必要があります。 4.5。 BouncyCastleライブラリで自己署名証明書を生成してから、.net形式(X509Certificate2オブジェクト)に変換しています。残念ながら私は秘密鍵をエクスポートすることはできません最新のフレームワークにアップグレードすると。ここでは、コードです:プライベートキーを持つ生成された証明書を.net 4.0/4.5のバイト配列にエクスポートできません

using System; 
using System.Diagnostics; 
using System.Security.Cryptography; 
using System.Security.Cryptography.X509Certificates; 
using Org.BouncyCastle.Asn1.X509; 
using Org.BouncyCastle.Crypto; 
using Org.BouncyCastle.Crypto.Generators; 
using Org.BouncyCastle.Crypto.Parameters; 
using Org.BouncyCastle.Crypto.Prng; 
using Org.BouncyCastle.Math; 
using Org.BouncyCastle.Security; 
using Org.BouncyCastle.X509; 

namespace X509CertificateExport 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var certificate = Generate(); 
      var exported = certificate.Export(X509ContentType.Pfx); 
      var imported = new X509Certificate2(exported, (string)null, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet); 

      Console.WriteLine("Certificate has private key: " + imported.HasPrivateKey); 
      Console.ReadKey(); 
     } 

     public static X509Certificate2 Generate() 
     { 
      var keyPairGenerator = new RsaKeyPairGenerator(); 
      var secureRandom = new SecureRandom(new CryptoApiRandomGenerator()); 
      keyPairGenerator.Init(new KeyGenerationParameters(secureRandom, 1024)); 
      var keyPair = keyPairGenerator.GenerateKeyPair(); 
      var publicKey = keyPair.Public; 
      var privateKey = (RsaPrivateCrtKeyParameters)keyPair.Private; 

      var generator = new X509V3CertificateGenerator(); 
      generator.SetSerialNumber(BigInteger.ProbablePrime(120, new Random())); 
      generator.SetSubjectDN(new X509Name("CN=Test")); 
      generator.SetIssuerDN(new X509Name("CN=Test")); 
      generator.SetNotAfter(DateTime.Now + new TimeSpan(10, 10, 10, 10)); 
      generator.SetNotBefore(DateTime.Now.Subtract(new TimeSpan(7, 0, 0, 0))); 
      generator.SetSignatureAlgorithm("MD5WithRSA"); 
      generator.SetPublicKey(publicKey); 

      var newCert = generator.Generate(privateKey); 
      var dotNetPrivateKey = ToDotNetKey(privateKey); 
      var dotNetCert = new X509Certificate2(DotNetUtilities.ToX509Certificate(newCert)); 
      dotNetCert.PrivateKey = dotNetPrivateKey; 

      return dotNetCert; 
     } 

     public static AsymmetricAlgorithm ToDotNetKey(RsaPrivateCrtKeyParameters privateKey) 
     { 
      var rsaProvider = new RSACryptoServiceProvider(); 
      var parameters = new RSAParameters 
      { 
       Modulus = privateKey.Modulus.ToByteArrayUnsigned(), 
       P = privateKey.P.ToByteArrayUnsigned(), 
       Q = privateKey.Q.ToByteArrayUnsigned(), 
       DP = privateKey.DP.ToByteArrayUnsigned(), 
       DQ = privateKey.DQ.ToByteArrayUnsigned(), 
       InverseQ = privateKey.QInv.ToByteArrayUnsigned(), 
       D = privateKey.Exponent.ToByteArrayUnsigned(), 
       Exponent = privateKey.PublicExponent.ToByteArrayUnsigned() 
      }; 

      rsaProvider.ImportParameters(parameters); 
      return rsaProvider; 
     } 
    } 
} 

生成された証明書によく見た後、私はPrivateKey.CspKeyContainerInfo.Exportableフラグは、.NET Framework 3.5のために真であることに気付きましたが、それ以降のバージョンのそれはスロー:

'Exportable' threw an exception of type 
'System.Security.Cryptography.CryptographicException'/Key does not exist 

PrivateKey.CspKeyContainerInfo.m_parameters.Flagsに表示される唯一の違いは次のとおりです。 .NET 3.5 - 'NoFlags'; .NET 4.5 - 'CreateEphemeralKey'。 「CreateEphemeralKey」は、関連するRSAオブジェクトが閉じられたときに解放される一時キーを作成すると述べています。 4.0フレームワークで導入され、かつて存在しなかったものです。私は明示的にCspParametersを作成することによってこのフラグを取り除こうとしました。

public static AsymmetricAlgorithm ToDotNetKey(RsaPrivateCrtKeyParameters privateKey) 
{ 
    var cspParams = new CspParameters 
    { 
     Flags = CspProviderFlags.UseMachineKeyStore 
    }; 

    var rsaProvider = new RSACryptoServiceProvider(cspParams); 
    // ... 

しかし運はありません。とにかく 'CreateEphemeralKey'が追加されているので、私は結果としてUseMachineKeyStore | CreateEphemeralKeyフラグを取得しています。どのように削除できますか?このフラグを無視して秘密鍵で証明書をエクスポートする方法はありますか?

+0

可能重複[挿入証明書ルートに、LOCALMACHINE証明書ストアは、.NETに失敗した(のPrivateKeyと)4](http://stackoverflow.com/questions/3625624/inserting-certificate-with-privatekey-in -root-localmachine-certificate-store) – albertjan

答えて

12

CspKeyContainerInfo.CspParameters.KeyContainerNameは、.NET 4.0および.NET 4.5でキーを作成した後で空ですが、.NET 3.5では自動生成されています。私はコンテナの一意の名前を設定しましたが、私は秘密鍵をエクスポートすることができます。

public static AsymmetricAlgorithm ToDotNetKey(RsaPrivateCrtKeyParameters privateKey) 
{ 
    var cspParams = new CspParameters 
    { 
      KeyContainerName = Guid.NewGuid().ToString(), 
      KeyNumber = (int)KeyNumber.Exchange, 
      Flags = CspProviderFlags.UseMachineKeyStore 
    }; 

    var rsaProvider = new RSACryptoServiceProvider(cspParams); 
    // ... 
+0

あなたは__the__人です!ありがとうございました! – albertjan

+0

これはクールな@ユーザー名、ユーザー名です。 –

+0

この「修正」もエラーを解決します。 SSL証明書の追加に失敗しました。エラー:1312 指定されたログオンセッションが存在しません。すでに終了している可能性があります。 – RcMan

関連する問題