2013-05-07 16 views
9

Oluşturulan sertifikaları bayt dizileri için ve özel anahtarlar ile vermem ve içe aktarmam gerekiyor ve .NET framework 4.0 kullanmadan herhangi bir sorunum yok ve 4.5. BouncyCastle kitaplığı ile kendinden imzalı sertifikalar oluşturuyorum ve bunları .net biçimine (X509Certificate2 nesnesi) dönüştürüyorum. Maalesef en yeni çerçeveye yükseltme ile özel anahtarları veremiyorum. İşte kod:Oluşturulan sertifikayı özel anahtarla, bayt dizisi .net 4.0/4.5 olarak veremiyor.

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; 
     } 
    } 
} 

üretilen sertifikaya yakından bakmak sonra PrivateKey.CspKeyContainerInfo.Exportable bayrak .NET framework 3.5 için geçerli olduğunu fark ettik, ancak sonraki sürümleri için atar:

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

Gördüğüm tek fark PrivateKey.CspKeyContainerInfo.m_parameters.Flags: .NET 3.5 - 'NoFlags'; .NET 4.5 - 'CreateEphemeralKey'. Belgeler, 'CreateEphemeralKey' ilişkili RSA nesnesi kapatıldığında yayımlanan geçici bir anahtar oluşturur. 4.0 çerçevesi ile tanıtıldı ve daha önce yoktu. Ben açıkça CspParameters oluşturarak bu bayrağı kapalı kurtulmak denedim:

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

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

ama hiç şansım. 'CreateEphemeralKey' zaten eklenir, bu yüzden sonuç olarak UseMachineKeyStore | CreateEphemeralKey bayraklarını alıyorum ve nasıl kaldıracağımı göremiyorum. Bu bayrak ve ihracat sertifikasını normalde özel anahtarla yok saymanın bir yolu var mı?

+0

olası yinelenen [ekleme Belgesi Root, LocalMachine sertifika deposu .NET başarısız (privatekey ile) 4] (http://stackoverflow.com/questions/3625624/inserting-certificate-with-privatekey-in -root-localmachine-certificate-store) – albertjan

cevap

12

.NET 4.0 ve .NET 4.5'te anahtar oluşturma işleminden sonra CspKeyContainerInfo.CspParameters.KeyContainerName boş olduğunu farkettim, ancak .NET 3.5'te otomatik olarak oluşturuldu. Kapsayıcı için benzersiz bir ad belirledim ve şimdi özel anahtarı verebiliyorum.

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); 
    // ... 
arasında
+0

Sen __the__ adamsın! Teşekkür ederim! – albertjan

+0

Bu bir @ kullanıcı adı, kullanıcı adı. –

+0

Bu "Düzeltme" ayrıca şu hatayı da giderir: SSL Sertifika eklenmesi başarısız oldu, Hata: 1312 Belirtilen bir oturum açma oturumu mevcut değil. Zaten iptal edilmiş olabilir. – RcMan