Genere un certificado autofirmado sobre la marcha

Busqué alrededor pero no encontré un claro ejemplo. Deseo crear un certificado autofirmado (auto) de confianza mediante progtwigción (c #) , siguiendo este paso:

PASO 1: cree el certificado de CA raíz sobre la marcha y agréguelo al almacén de certificados en la carpeta “Autoridades de certificación de raíz confiable”

Quiero hacer exactamente lo que hace esta herramienta de línea de comando:

makecert.exe -sk RootCA -sky firma -pe -n CN = MY_CA -r -sr LocalMachine -ss Root MyCA.cer

PASO 2: cree un certificado basado en el certificado de CA raíz creado anteriormente y colóquelo en el almacén de certificados, en la carpeta “Personal”

Quiero hacer exactamente lo que hace esta herramienta de línea de comando:

makecert.exe -sk servidor -sky exchange -pe -n CN = 127.0.0.1 -ir LocalMachine -is Root -ic MyCA.cer -sr LocalMachine -ss My MyCertificate.cer

Quiero obtener esto:
enter image description here

Lo hice (vea el siguiente código – PASO 1), no sé cómo hacer STEP2, cualquier ayuda sería apreciada. Las máquinas de destino son Windows XP / Seven. Probé tanto el enfoque .net puro como la biblioteca BouncyCastle .

//STEP1 mycerRoot=generateRootCertV1("MY_CA"); //tried also generateRootCertV2(BouncyCastle) addCertToStore(mycerRoot, StoreName.Root, StoreLocation.LocalMachine); //STEP2 mycer=generateCert("127.0.0.1",mycerRoot);//?????? <-- Something like that How to implement generateCert??? addCertToStore(mycer, StoreName.My, StoreLocation.LocalMachine); public static Org.BouncyCastle.X509.X509Certificate generateRootCertV2(string certName) { X509V1CertificateGenerator certGen = new X509V1CertificateGenerator(); X509Name CN = new X509Name("CN=" + certName); RsaKeyPairGenerator keypairgen = new RsaKeyPairGenerator(); keypairgen.Init(new KeyGenerationParameters(new SecureRandom(new CryptoApiRandomGenerator()), 1024)); AsymmetricCipherKeyPair keypair = keypairgen.GenerateKeyPair(); certGen.SetSerialNumber(BigInteger.ProbablePrime(120, new Random())); certGen.SetIssuerDN(CN); certGen.SetNotAfter(DateTime.MaxValue); certGen.SetNotBefore(DateTime.Now.Subtract(new TimeSpan(7, 0, 0, 0))); certGen.SetSubjectDN(CN); certGen.SetPublicKey(keypair.Public); certGen.SetSignatureAlgorithm("MD5WithRSA"); Org.BouncyCastle.X509.X509Certificate newCert = certGen.Generate(keypair.Private); return newCert; } public static X509Certificate2 GenerateRootCertV1(string HostNameOrIP_or_CertName) { X509Certificate2 cert = null; try { using (CryptContext ctx = new CryptContext()) { ctx.Open(); cert = ctx.CreateSelfSignedCertificate( new SelfSignedCertProperties { IsPrivateKeyExportable = true, KeyBitLength = 4096, Name = new X500DistinguishedName("cn=" + HostNameOrIP_or_CertName), ValidFrom = DateTime.Today.AddDays(-1), ValidTo = DateTime.Today.AddYears(20), }); } } catch (Exception ex) { } return cert; } public static bool addCertToStore(X509Certificate2 cert, StoreName st, StoreLocation sl) { bool bRet = false; try { X509Store store = new X509Store(st, sl); store.Open(OpenFlags.ReadWrite); if (cert != null) { byte[] pfx = cert.Export(X509ContentType.Pfx); cert = new X509Certificate2(pfx, (string)null, X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.MachineKeySet); if (!certExists(store, cert.SubjectName.Name)) { store.Add(cert); bRet = true; } } store.Close(); } catch { } return bRet; } 

Edité la respuesta para hacer primero un certificado raíz y luego emitir un certificado de entidad final. A continuación se muestra un ejemplo de generación de certificado de autobronce a través de rebote:

 public static X509Certificate2 GenerateSelfSignedCertificate(string subjectName, string issuerName, AsymmetricKeyParameter issuerPrivKey, int keyStrength = 2048) { // Generating Random Numbers var randomGenerator = new CryptoApiRandomGenerator(); var random = new SecureRandom(randomGenerator); // The Certificate Generator var certificateGenerator = new X509V3CertificateGenerator(); // Serial Number var serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random); certificateGenerator.SetSerialNumber(serialNumber); // Signature Algorithm const string signatureAlgorithm = "SHA256WithRSA"; certificateGenerator.SetSignatureAlgorithm(signatureAlgorithm); // Issuer and Subject Name var subjectDN = new X509Name(subjectName); var issuerDN = new X509Name(issuerName); certificateGenerator.SetIssuerDN(issuerDN); certificateGenerator.SetSubjectDN(subjectDN); // Valid For var notBefore = DateTime.UtcNow.Date; var notAfter = notBefore.AddYears(2); certificateGenerator.SetNotBefore(notBefore); certificateGenerator.SetNotAfter(notAfter); // Subject Public Key AsymmetricCipherKeyPair subjectKeyPair; var keyGenerationParameters = new KeyGenerationParameters(random, keyStrength); var keyPairGenerator = new RsaKeyPairGenerator(); keyPairGenerator.Init(keyGenerationParameters); subjectKeyPair = keyPairGenerator.GenerateKeyPair(); certificateGenerator.SetPublicKey(subjectKeyPair.Public); // Generating the Certificate var issuerKeyPair = subjectKeyPair; // selfsign certificate var certificate = certificateGenerator.Generate(issuerPrivKey, random); // correcponding private key PrivateKeyInfo info = PrivateKeyInfoFactory.CreatePrivateKeyInfo(subjectKeyPair.Private); // merge into X509Certificate2 var x509 = new System.Security.Cryptography.X509Certificates.X509Certificate2(certificate.GetEncoded()); var seq = (Asn1Sequence)Asn1Object.FromByteArray(info.PrivateKey.GetDerEncoded()); if (seq.Count != 9) throw new PemException("malformed sequence in RSA private key"); var rsa = new RsaPrivateKeyStructure(seq); RsaPrivateCrtKeyParameters rsaparams = new RsaPrivateCrtKeyParameters( rsa.Modulus, rsa.PublicExponent, rsa.PrivateExponent, rsa.Prime1, rsa.Prime2, rsa.Exponent1, rsa.Exponent2, rsa.Coefficient); x509.PrivateKey = DotNetUtilities.ToRSA(rsaparams); return x509; } public static AsymmetricKeyParameter GenerateCACertificate(string subjectName, int keyStrength = 2048) { // Generating Random Numbers var randomGenerator = new CryptoApiRandomGenerator(); var random = new SecureRandom(randomGenerator); // The Certificate Generator var certificateGenerator = new X509V3CertificateGenerator(); // Serial Number var serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random); certificateGenerator.SetSerialNumber(serialNumber); // Signature Algorithm const string signatureAlgorithm = "SHA256WithRSA"; certificateGenerator.SetSignatureAlgorithm(signatureAlgorithm); // Issuer and Subject Name var subjectDN = new X509Name(subjectName); var issuerDN = subjectDN; certificateGenerator.SetIssuerDN(issuerDN); certificateGenerator.SetSubjectDN(subjectDN); // Valid For var notBefore = DateTime.UtcNow.Date; var notAfter = notBefore.AddYears(2); certificateGenerator.SetNotBefore(notBefore); certificateGenerator.SetNotAfter(notAfter); // Subject Public Key AsymmetricCipherKeyPair subjectKeyPair; var keyGenerationParameters = new KeyGenerationParameters(random, keyStrength); var keyPairGenerator = new RsaKeyPairGenerator(); keyPairGenerator.Init(keyGenerationParameters); subjectKeyPair = keyPairGenerator.GenerateKeyPair(); certificateGenerator.SetPublicKey(subjectKeyPair.Public); // Generating the Certificate var issuerKeyPair = subjectKeyPair; // selfsign certificate var certificate = certificateGenerator.Generate(issuerKeyPair.Private, random); var x509 = new System.Security.Cryptography.X509Certificates.X509Certificate2(certificate.GetEncoded()); // Add CA certificate to Root store addCertToStore(cert, StoreName.Root, StoreLocation.CurrentUser); return issuerKeyPair.Private; } 

y agregar a la tienda (su código ligeramente modificado):

 public static bool addCertToStore(System.Security.Cryptography.X509Certificates.X509Certificate2 cert, System.Security.Cryptography.X509Certificates.StoreName st, System.Security.Cryptography.X509Certificates.StoreLocation sl) { bool bRet = false; try { X509Store store = new X509Store(st, sl); store.Open(OpenFlags.ReadWrite); store.Add(cert); store.Close(); } catch { } return bRet; } 

y uso:

 var caPrivKey = GenerateCACertificate("CN=root ca"); var cert = GenerateSelfSignedCertificate("CN=127.0.01", "CN=root ca", caPrivKey); addCertToStore(cert, StoreName.My, StoreLocation.CurrentUser); 

No he comstackdo este código de ejemplo después de los comentarios de @wakeupneo. @wakeupneo puede editar ligeramente el código y agregar las extensiones adecuadas a cada certificado.

Ok, gracias por la ayuda, aquí está el código de trabajo:

 private void button_Click(object sender, EventArgs e) { AsymmetricKeyParameter myCAprivateKey = null; //generate a root CA cert and obtain the privateKey X509Certificate2 MyRootCAcert = GenerateCACertificate("CN=MYTESTCA", ref myCAprivateKey); //add CA cert to store addCertToStore(MyRootCAcert, StoreName.Root, StoreLocation.LocalMachine); //generate cert based on the CA cert privateKey X509Certificate2 MyCert = GenerateSelfSignedCertificate("CN=127.0.01", "CN=MYTESTCA", myCAprivateKey); //add cert to store addCertToStore(MyCert, StoreName.My, StoreLocation.LocalMachine); MessageBox.Show("Done!"); } public static X509Certificate2 GenerateSelfSignedCertificate(string subjectName, string issuerName, AsymmetricKeyParameter issuerPrivKey) { const int keyStrength = 2048; // Generating Random Numbers CryptoApiRandomGenerator randomGenerator = new CryptoApiRandomGenerator(); SecureRandom random = new SecureRandom(randomGenerator); // The Certificate Generator X509V3CertificateGenerator certificateGenerator = new X509V3CertificateGenerator(); // Serial Number BigInteger serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random); certificateGenerator.SetSerialNumber(serialNumber); // Signature Algorithm const string signatureAlgorithm = "SHA256WithRSA"; certificateGenerator.SetSignatureAlgorithm(signatureAlgorithm); // Issuer and Subject Name X509Name subjectDN = new X509Name(subjectName); X509Name issuerDN = new X509Name(issuerName); certificateGenerator.SetIssuerDN(issuerDN); certificateGenerator.SetSubjectDN(subjectDN); // Valid For DateTime notBefore = DateTime.UtcNow.Date; DateTime notAfter = notBefore.AddYears(2); certificateGenerator.SetNotBefore(notBefore); certificateGenerator.SetNotAfter(notAfter); // Subject Public Key AsymmetricCipherKeyPair subjectKeyPair; var keyGenerationParameters = new KeyGenerationParameters(random, keyStrength); var keyPairGenerator = new RsaKeyPairGenerator(); keyPairGenerator.Init(keyGenerationParameters); subjectKeyPair = keyPairGenerator.GenerateKeyPair(); certificateGenerator.SetPublicKey(subjectKeyPair.Public); // Generating the Certificate AsymmetricCipherKeyPair issuerKeyPair = subjectKeyPair; // selfsign certificate Org.BouncyCastle.X509.X509Certificate certificate = certificateGenerator.Generate(issuerPrivKey, random); // correcponding private key PrivateKeyInfo info = PrivateKeyInfoFactory.CreatePrivateKeyInfo(subjectKeyPair.Private); // merge into X509Certificate2 X509Certificate2 x509 = new System.Security.Cryptography.X509Certificates.X509Certificate2(certificate.GetEncoded()); Asn1Sequence seq = (Asn1Sequence)Asn1Object.FromByteArray(info.PrivateKey.GetDerEncoded()); if (seq.Count != 9) { //throw new PemException("malformed sequence in RSA private key"); } RsaPrivateKeyStructure rsa = new RsaPrivateKeyStructure(seq); RsaPrivateCrtKeyParameters rsaparams = new RsaPrivateCrtKeyParameters( rsa.Modulus, rsa.PublicExponent, rsa.PrivateExponent, rsa.Prime1, rsa.Prime2, rsa.Exponent1, rsa.Exponent2, rsa.Coefficient); x509.PrivateKey = DotNetUtilities.ToRSA(rsaparams); return x509; } public static X509Certificate2 GenerateCACertificate(string subjectName, ref AsymmetricKeyParameter CaPrivateKey) { const int keyStrength = 2048; // Generating Random Numbers CryptoApiRandomGenerator randomGenerator = new CryptoApiRandomGenerator(); SecureRandom random = new SecureRandom(randomGenerator); // The Certificate Generator X509V3CertificateGenerator certificateGenerator = new X509V3CertificateGenerator(); // Serial Number BigInteger serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random); certificateGenerator.SetSerialNumber(serialNumber); // Signature Algorithm const string signatureAlgorithm = "SHA256WithRSA"; certificateGenerator.SetSignatureAlgorithm(signatureAlgorithm); // Issuer and Subject Name X509Name subjectDN = new X509Name(subjectName); X509Name issuerDN = subjectDN; certificateGenerator.SetIssuerDN(issuerDN); certificateGenerator.SetSubjectDN(subjectDN); // Valid For DateTime notBefore = DateTime.UtcNow.Date; DateTime notAfter = notBefore.AddYears(2); certificateGenerator.SetNotBefore(notBefore); certificateGenerator.SetNotAfter(notAfter); // Subject Public Key AsymmetricCipherKeyPair subjectKeyPair; KeyGenerationParameters keyGenerationParameters = new KeyGenerationParameters(random, keyStrength); RsaKeyPairGenerator keyPairGenerator = new RsaKeyPairGenerator(); keyPairGenerator.Init(keyGenerationParameters); subjectKeyPair = keyPairGenerator.GenerateKeyPair(); certificateGenerator.SetPublicKey(subjectKeyPair.Public); // Generating the Certificate AsymmetricCipherKeyPair issuerKeyPair = subjectKeyPair; // selfsign certificate Org.BouncyCastle.X509.X509Certificate certificate = certificateGenerator.Generate(issuerKeyPair.Private, random); X509Certificate2 x509 = new System.Security.Cryptography.X509Certificates.X509Certificate2(certificate.GetEncoded()); CaPrivateKey = issuerKeyPair.Private; return x509; //return issuerKeyPair.Private; } public static bool addCertToStore(System.Security.Cryptography.X509Certificates.X509Certificate2 cert, System.Security.Cryptography.X509Certificates.StoreName st, System.Security.Cryptography.X509Certificates.StoreLocation sl) { bool bRet = false; try { X509Store store = new X509Store(st, sl); store.Open(OpenFlags.ReadWrite); store.Add(cert); store.Close(); } catch { } return bRet; } 

Después de integrar los cambios de varias publicaciones, finalmente conseguí que este código funcionara. ¡Espero que esto ahorre a muchas personas mucho tiempo!

 static void Main(string[] args) { AsymmetricKeyParameter caPrivateKey = null; var caCert = GenerateCACertificate("CN=MyROOTCA", ref caPrivateKey); addCertToStore(caCert, StoreName.Root, StoreLocation.LocalMachine); var clientCert = GenerateSelfSignedCertificate("CN=127.0.0.1", "CN=MyROOTCA", caPrivateKey); var p12 = clientCert.Export(X509ContentType.Pfx); addCertToStore(new X509Certificate2(p12, (string)null, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet), StoreName.My, StoreLocation.LocalMachine); } public static X509Certificate2 GenerateSelfSignedCertificate(string subjectName, string issuerName, AsymmetricKeyParameter issuerPrivKey) { const int keyStrength = 2048; // Generating Random Numbers CryptoApiRandomGenerator randomGenerator = new CryptoApiRandomGenerator(); SecureRandom random = new SecureRandom(randomGenerator); // The Certificate Generator X509V3CertificateGenerator certificateGenerator = new X509V3CertificateGenerator(); // Serial Number BigInteger serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random); certificateGenerator.SetSerialNumber(serialNumber); // Signature Algorithm const string signatureAlgorithm = "SHA256WithRSA"; certificateGenerator.SetSignatureAlgorithm(signatureAlgorithm); // Issuer and Subject Name X509Name subjectDN = new X509Name(subjectName); X509Name issuerDN = new X509Name(issuerName); certificateGenerator.SetIssuerDN(issuerDN); certificateGenerator.SetSubjectDN(subjectDN); // Valid For DateTime notBefore = DateTime.UtcNow.Date; DateTime notAfter = notBefore.AddYears(2); certificateGenerator.SetNotBefore(notBefore); certificateGenerator.SetNotAfter(notAfter); // Subject Public Key AsymmetricCipherKeyPair subjectKeyPair; var keyGenerationParameters = new KeyGenerationParameters(random, keyStrength); var keyPairGenerator = new RsaKeyPairGenerator(); keyPairGenerator.Init(keyGenerationParameters); subjectKeyPair = keyPairGenerator.GenerateKeyPair(); certificateGenerator.SetPublicKey(subjectKeyPair.Public); // Generating the Certificate AsymmetricCipherKeyPair issuerKeyPair = subjectKeyPair; // selfsign certificate Org.BouncyCastle.X509.X509Certificate certificate = certificateGenerator.Generate(issuerPrivKey, random); // correcponding private key PrivateKeyInfo info = PrivateKeyInfoFactory.CreatePrivateKeyInfo(subjectKeyPair.Private); // merge into X509Certificate2 X509Certificate2 x509 = new System.Security.Cryptography.X509Certificates.X509Certificate2(certificate.GetEncoded()); Asn1Sequence seq = (Asn1Sequence)Asn1Object.FromByteArray(info.PrivateKey.GetDerEncoded()); if (seq.Count != 9) { //throw new PemException("malformed sequence in RSA private key"); } RsaPrivateKeyStructure rsa = new RsaPrivateKeyStructure(seq); RsaPrivateCrtKeyParameters rsaparams = new RsaPrivateCrtKeyParameters( rsa.Modulus, rsa.PublicExponent, rsa.PrivateExponent, rsa.Prime1, rsa.Prime2, rsa.Exponent1, rsa.Exponent2, rsa.Coefficient); x509.PrivateKey = ToDotNetKey(rsaparams); //x509.PrivateKey = DotNetUtilities.ToRSA(rsaparams); return x509; } 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); 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; } public static X509Certificate2 GenerateCACertificate(string subjectName, ref AsymmetricKeyParameter CaPrivateKey) { const int keyStrength = 2048; // Generating Random Numbers CryptoApiRandomGenerator randomGenerator = new CryptoApiRandomGenerator(); SecureRandom random = new SecureRandom(randomGenerator); // The Certificate Generator X509V3CertificateGenerator certificateGenerator = new X509V3CertificateGenerator(); // Serial Number BigInteger serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random); certificateGenerator.SetSerialNumber(serialNumber); // Signature Algorithm const string signatureAlgorithm = "SHA256WithRSA"; certificateGenerator.SetSignatureAlgorithm(signatureAlgorithm); // Issuer and Subject Name X509Name subjectDN = new X509Name(subjectName); X509Name issuerDN = subjectDN; certificateGenerator.SetIssuerDN(issuerDN); certificateGenerator.SetSubjectDN(subjectDN); // Valid For DateTime notBefore = DateTime.UtcNow.Date; DateTime notAfter = notBefore.AddYears(2); certificateGenerator.SetNotBefore(notBefore); certificateGenerator.SetNotAfter(notAfter); // Subject Public Key AsymmetricCipherKeyPair subjectKeyPair; KeyGenerationParameters keyGenerationParameters = new KeyGenerationParameters(random, keyStrength); RsaKeyPairGenerator keyPairGenerator = new RsaKeyPairGenerator(); keyPairGenerator.Init(keyGenerationParameters); subjectKeyPair = keyPairGenerator.GenerateKeyPair(); certificateGenerator.SetPublicKey(subjectKeyPair.Public); // Generating the Certificate AsymmetricCipherKeyPair issuerKeyPair = subjectKeyPair; // selfsign certificate Org.BouncyCastle.X509.X509Certificate certificate = certificateGenerator.Generate(issuerKeyPair.Private, random); X509Certificate2 x509 = new System.Security.Cryptography.X509Certificates.X509Certificate2(certificate.GetEncoded()); CaPrivateKey = issuerKeyPair.Private; return x509; //return issuerKeyPair.Private; } public static bool addCertToStore(System.Security.Cryptography.X509Certificates.X509Certificate2 cert, System.Security.Cryptography.X509Certificates.StoreName st, System.Security.Cryptography.X509Certificates.StoreLocation sl) { bool bRet = false; try { X509Store store = new X509Store(st, sl); store.Open(OpenFlags.ReadWrite); store.Add(cert); store.Close(); } catch { } return bRet; } 

Estamos usando el siguiente código en nuestras pruebas

(a) Dependencia de Nuget: Bouncy Castle 1.7.0

  

(b) Generador de certificados autofirmados, intermedios y CA:

 namespace Transport.Tests { using System; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using Org.BouncyCastle.Asn1; using Org.BouncyCastle.Asn1.Pkcs; 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.OpenSsl; using Org.BouncyCastle.Pkcs; using Org.BouncyCastle.Security; using Org.BouncyCastle.Utilities; using Org.BouncyCastle.X509; using Org.BouncyCastle.X509.Extension; public class X509Certificate2Builder { public string SubjectName { set { _subjectName = value; } } public string IssuerName { set { _issuerName = value; } } public AsymmetricAlgorithm IssuerPrivateKey { set { _issuerPrivateKey = value; } } public X509Certificate2 Issuer { set { _issuer = value; _issuerName = value.IssuerName.Name; if (value.HasPrivateKey) _issuerPrivateKey = value.PrivateKey; } } public int? KeyStrength { set { _keyStrength = value ?? 2048; } } public DateTime? NotBefore { set { _notBefore = value; } } public DateTime? NotAfter { set { _notAfter = value; } } public bool Intermediate { set { _intermediate = value; } } private string _subjectName; private X509Certificate2 _issuer; private string _issuerName; private AsymmetricAlgorithm _issuerPrivateKey; private int _keyStrength = 2048; private DateTime? _notBefore; private DateTime? _notAfter; private bool _intermediate = true; public X509Certificate2 Build() { // Generating Random Numbers var randomGenerator = new CryptoApiRandomGenerator(); var random = new SecureRandom(randomGenerator); // The Certificate Generator var certificateGenerator = new X509V3CertificateGenerator(); // Serial Number var serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(long.MaxValue), random); certificateGenerator.SetSerialNumber(serialNumber); // Signature Algorithm certificateGenerator.SetSignatureAlgorithm("SHA256WithRSA"); // Issuer and Subject Name certificateGenerator.SetIssuerDN(new X509Name(_issuerName ?? _subjectName)); certificateGenerator.SetSubjectDN(new X509Name(_subjectName)); // Authority Key Identifier if (_issuer != null) { var authorityKeyIdentifier = new AuthorityKeyIdentifierStructure( DotNetUtilities.FromX509Certificate(_issuer)); certificateGenerator.AddExtension( X509Extensions.AuthorityKeyIdentifier.Id, false, authorityKeyIdentifier); } // Basic Constraints - certificate is allowed to be used as intermediate. certificateGenerator.AddExtension( X509Extensions.BasicConstraints.Id, true, new BasicConstraints(_intermediate)); // Valid For certificateGenerator.SetNotBefore(_notBefore ?? DateTime.UtcNow.Date); certificateGenerator.SetNotAfter(_notAfter ?? DateTime.UtcNow.Date.AddYears(2)); // Subject Public Key var keyGenerationParameters = new KeyGenerationParameters(random, _keyStrength); var keyPairGenerator = new RsaKeyPairGenerator(); keyPairGenerator.Init(keyGenerationParameters); var subjectKeyPair = keyPairGenerator.GenerateKeyPair(); var issuerKeyPair = _issuerPrivateKey == null ? subjectKeyPair : DotNetUtilities.GetKeyPair(_issuerPrivateKey); certificateGenerator.SetPublicKey(subjectKeyPair.Public); // selfsign certificate var certificate = certificateGenerator.Generate(issuerKeyPair.Private, random); // merge into X509Certificate2 return new X509Certificate2(certificate.GetEncoded()) { PrivateKey = ConvertToRsaPrivateKey(subjectKeyPair) }; } private static AsymmetricAlgorithm ConvertToRsaPrivateKey(AsymmetricCipherKeyPair keyPair) { var keyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(keyPair.Private); var seq = (Asn1Sequence) Asn1Object.FromByteArray(keyInfo.PrivateKey.GetDerEncoded()); if (seq.Count != 9) throw new PemException("malformed sequence in RSA private key"); var rsa = new RsaPrivateKeyStructure(seq); var rsaparams = new RsaPrivateCrtKeyParameters( rsa.Modulus, rsa.PublicExponent, rsa.PrivateExponent, rsa.Prime1, rsa.Prime2, rsa.Exponent1, rsa.Exponent2, rsa.Coefficient); return DotNetUtilities.ToRSA(rsaparams); } } } 

(c) Uso de ejemplo:

 var ca1 = new X509Certificate2Builder {SubjectName = "CN=Test CA1"}.Build(); var in1A = new X509Certificate2Builder { SubjectName = "CN=Intermediate 1A", Issuer = ca1}.Build(); var in1B = new X509Certificate2Builder { SubjectName = "CN=Intermediate 1B", Issuer = in1A}.Build(); var cert1 = new X509Certificate2Builder { SubjectName = "CN=Test 1", Issuer = in1B, Intermediate = false }.Build(); var cert1B = new X509Certificate2Builder { SubjectName = "CN=Test 1B", Issuer = cert1}.Build(); var ca2 = new X509Certificate2Builder { SubjectName = "CN=Test CA2"}.Build(); var cert2 = new X509Certificate2Builder { SubjectName = "CN=Test 2", Issuer = ca2, Intermediate = false}.Build(); var invalidCert1 = new X509Certificate2Builder { SubjectName = "CN=Invalid 1", IssuerName = ca1.SubjectName.Name, IssuerPrivateKey = ca2.PrivateKey }.Build(); var invalidCert2 = new X509Certificate2Builder { SubjectName = "CN=Invalid 2", Issuer = ca2, NotBefore = DateTime.Now.AddDays(1) }.Build(); 

Así que después de un largo tiempo refinaré mi respuesta. Mi tarea original era crear un certificado sobre la marcha para un servicio de WCF.

Mi aplicación de servicio de Windows tiene un servicio WCF y quiero crear el canal en tiempo de ejecución con la creación del certificado asociado si no está presente en la máquina local.

Todo el código anterior es la forma correcta de hacerlo, pero falta una pieza. Debe crear un certificado con una clave privada exportable incorporada.

Ver este enlace

Este es el enfoque en la parte crítica del fragmento para generar la clave privada:

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

Si no haces esto, cuando ejecutas el comando netsh obtienes el error 1312. ie del comando netsh:

netsh http add sslcert ipport = 192.168.0.15: 8081 certhash = 5424476237fc2785ed2d0fd620a9131d7c999f6f appid = {02639d71-0935-35e8-9d1b-9dd1a2a34627}