2010-09-22 16 views
34

Biz programlı C# ve BouncyCastle kitaplığı kullanarak (özel anahtar dahil) bir X 509 sertifika üretmek için çalışıyoruz. Bazı kodları this sample by Felix Kollmann'dan kullanmayı denedik, ancak sertifikanın özel anahtar kısmı null değerini döndürdü. Kod ve birim test aşağıdaki gibidir:Sadece C# kullanarak programlı bir X509 sertifikası oluşturmak mümkün mü?

using System; 
using System.Collections; 
using Org.BouncyCastle.Asn1; 
using Org.BouncyCastle.Asn1.X509; 
using Org.BouncyCastle.Crypto; 
using Org.BouncyCastle.Crypto.Generators; 
using Org.BouncyCastle.Crypto.Prng; 
using Org.BouncyCastle.Math; 
using Org.BouncyCastle.Security; 
using Org.BouncyCastle.X509; 

namespace MyApp 
{ 
    public class CertificateGenerator 
    { 
     /// <summary> 
     /// 
     /// </summary> 
     /// <remarks>Based on <see cref="http://www.fkollmann.de/v2/post/Creating-certificates-using-BouncyCastle.aspx"/></remarks> 
     /// <param name="subjectName"></param> 
     /// <returns></returns> 
     public static byte[] GenerateCertificate(string subjectName) 
     { 
      var kpgen = new RsaKeyPairGenerator(); 

      kpgen.Init(new KeyGenerationParameters(new SecureRandom(new CryptoApiRandomGenerator()), 1024)); 

      var kp = kpgen.GenerateKeyPair(); 

      var gen = new X509V3CertificateGenerator(); 

      var certName = new X509Name("CN=" + subjectName); 
      var serialNo = BigInteger.ProbablePrime(120, new Random()); 

      gen.SetSerialNumber(serialNo); 
      gen.SetSubjectDN(certName); 
      gen.SetIssuerDN(certName); 
      gen.SetNotAfter(DateTime.Now.AddYears(100)); 
      gen.SetNotBefore(DateTime.Now.Subtract(new TimeSpan(7, 0, 0, 0))); 
      gen.SetSignatureAlgorithm("MD5WithRSA"); 
      gen.SetPublicKey(kp.Public); 

      gen.AddExtension(
       X509Extensions.AuthorityKeyIdentifier.Id, 
       false, 
       new AuthorityKeyIdentifier(
        SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(kp.Public), 
        new GeneralNames(new GeneralName(certName)), 
        serialNo)); 

      gen.AddExtension(
       X509Extensions.ExtendedKeyUsage.Id, 
       false, 
       new ExtendedKeyUsage(new ArrayList() { new DerObjectIdentifier("1.3.6.1.5.5.7.3.1") })); 

      var newCert = gen.Generate(kp.Private); 
      return DotNetUtilities.ToX509Certificate(newCert).Export(System.Security.Cryptography.X509Certificates.X509ContentType.Pkcs12, "password"); 
     } 
    } 
} 

Birim testi:

using System.Security.Cryptography; 
using System.Security.Cryptography.X509Certificates; 
using Microsoft.VisualStudio.TestTools.UnitTesting; 

namespace MyApp 
{ 
    [TestClass] 
    public class CertificateGeneratorTests 
    { 
     [TestMethod] 
     public void GenerateCertificate_Test_ValidCertificate() 
     { 
      // Arrange 
      string subjectName = "test"; 

      // Act 
      byte[] actual = CertificateGenerator.GenerateCertificate(subjectName); 

      // Assert 
      var cert = new X509Certificate2(actual, "password"); 
      Assert.AreEqual("CN=" + subjectName, cert.Subject); 
      Assert.IsInstanceOfType(cert.PrivateKey, typeof(RSACryptoServiceProvider)); 
     } 
    } 
} 

cevap

27

Sadece netleştirmek için bir X.509 sertifikası özel anahtarı içermez. kelimesi belgesi bazen sertifika ve özel anahtar kombinasyonu temsil etmek amacı dışında kullanılması, ancak iki ayrı varlıklardır. Sertifikaları kullanmanın tüm amacı, gizli kalması gereken özel anahtarı göndermeden, onları daha fazla veya daha açık bir şekilde göndermektir. Bir X509Certificate2 nesne (kendi PrivateKey özelliği aracılığıyla) onunla ilişkili bir özel anahtar olabilir, ama bu sınıfın tasarımın bir parçası olarak sadece bir kolaylık var.

İlk BouncyCastle kod örneğinizde, newCert gerçekten yalnızca sertifikadır ve DotNetUtilities.ToX509Certificate(newCert) yalnızca sertifikadan oluşturulur.

PKCS # 12 biçiminin özel bir anahtarın bulunmasını gerektirdiğini düşünürsek, aşağıdaki bölümün bile işe yaradığını fark ettim (özel anahtarı bilmeyen bir sertifikada çağırıyorsanız) :

.Export(System.Security.Cryptography.X509Certificates.X509ContentType.Pkcs12, 
    "password"); 

(gen.Generate(kp.Private) özel anahtarı kullanarak sertifikayı imzalar, ancak anlamlı olmaz sertifikası, özel anahtar koymak değildir.)

Eğer yöntem hem dönmek istiyorsanız sertifika ve özel anahtar ya could:

  • Dönüş bir X509Certificate2 nesne hangi PrivateKey mülkiyet
  • kurmak PKCS # 12 mağaza başlatıldı ve (bir dosya sanki) onun byte[] içeriği döndürür ettik. Step 3 in the link you've sent (mirror), PKCS # 12 deposunun nasıl oluşturulacağını açıklar.

X.509 sertifikasının kendisi için byte[] (DER) yapısının döndürülmesi, özel anahtarı içermez.

ana endişe (test duruma göre) Eğer sertifika RSA anahtar çifti inşa edildiğini kontrol etmektir, bunun yerine ortak anahtarına türünü kontrol edebilirsiniz.

+0

+1, çok güzel bir açıklama. PKCS # 12 spesifikasyonuna baktın mı? Bu * BRUTAL *! PKCS # 12 ile hemen hemen her şey mümkündür. Özel bir anahtara sahip olmanıza gerek yok. Genellikle, PKCS # 12, bir özel anahtarı ve ilişkili bir sertifikayı tutmak için kullanılır, ancak başka olasılıklar da vardır. –

+4

3. adım için sağlanan bağlantı bozuk görünüyor. Neyse ki archive.org hala içeriği şu şekildedir: http://web.archive.org/web/20100504192226/http://www.fkollmann.de/v2/post/Creating-certificates-using-BouncyCastle.aspx – Kyle

+0

@Zenox, cevabımı düzenlemek ve değiştirmek için çekinmeyin, bu size birkaç puan vermelidir. – Bruno

6

Bu eski bir yazı olduğunu fark ama sürecinden geçmesi bu mükemmel makaleleri bulundu:

Using Bouncy Castle from .NET

+1

kullanarak CA imzalı sertifikalar yapmak, meta arkadaşınız: https://meta.stackexchange.com/questions/8231/are-answers-that-just- link-link-başka-gerçekten-iyi-cevaplar – MatthewMartin

+1

Bağlantı için güvenlik uyarı alma .. –

+1

Bağlantıyı güncelledim. – haymansfield

İlgili konular