// https://stackoverflow.com/questions/6128541/bouncycastle-privatekey-to-x509certificate2-privatekey public static Org.BouncyCastle.X509.X509Certificate CreateX509Cert(string certName) { var keypairgen = new Org.BouncyCastle.Crypto.Generators.RsaKeyPairGenerator(); keypairgen.Init(new Org.BouncyCastle.Crypto.KeyGenerationParameters( new Org.BouncyCastle.Security.SecureRandom( new Org.BouncyCastle.Crypto.Prng.CryptoApiRandomGenerator() ) , 1024 ) ); var keypair = keypairgen.GenerateKeyPair(); var gen = new Org.BouncyCastle.X509.X509V3CertificateGenerator(); var CN = new Org.BouncyCastle.Asn1.X509.X509Name("CN=" + certName); var SN = Org.BouncyCastle.Math.BigInteger.ProbablePrime(120, new Random()); gen.SetSerialNumber(SN); gen.SetSubjectDN(CN); gen.SetIssuerDN(CN); gen.SetNotAfter(DateTime.Now.AddYears(1)); gen.SetNotBefore(DateTime.Now.Subtract(new TimeSpan(7, 0, 0, 0))); gen.SetSignatureAlgorithm("MD5WithRSA"); gen.SetPublicKey(keypair.Public); gen.AddExtension( Org.BouncyCastle.Asn1.X509.X509Extensions.AuthorityKeyIdentifier.Id, false, new Org.BouncyCastle.Asn1.X509.AuthorityKeyIdentifier( Org.BouncyCastle.X509.SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(keypair.Public), new Org.BouncyCastle.Asn1.X509.GeneralNames(new Org.BouncyCastle.Asn1.X509.GeneralName(CN)), SN )); gen.AddExtension( Org.BouncyCastle.Asn1.X509.X509Extensions.ExtendedKeyUsage.Id, false, new Org.BouncyCastle.Asn1.X509.ExtendedKeyUsage(new ArrayList() { new Org.BouncyCastle.Asn1.DerObjectIdentifier("1.3.6.1.5.5.7.3.1") })); Org.BouncyCastle.X509.X509Certificate newCert = gen.Generate(keypair.Private); return(newCert); }
// http://stackoverflow.com/questions/36942094/how-can-i-generate-a-self-signed-cert-without-using-obsolete-bouncycastle-1-7-0 public static System.Security.Cryptography.X509Certificates.X509Certificate2 CreateX509Cert2(string certName) { var keypairgen = new Org.BouncyCastle.Crypto.Generators.RsaKeyPairGenerator(); keypairgen.Init(new Org.BouncyCastle.Crypto.KeyGenerationParameters( new Org.BouncyCastle.Security.SecureRandom( new Org.BouncyCastle.Crypto.Prng.CryptoApiRandomGenerator() ) , 1024 ) ); Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair keypair = keypairgen.GenerateKeyPair(); // --- Until here we generate a keypair var random = new Org.BouncyCastle.Security.SecureRandom( new Org.BouncyCastle.Crypto.Prng.CryptoApiRandomGenerator() ); // SHA1WITHRSA // SHA256WITHRSA // SHA384WITHRSA // SHA512WITHRSA // SHA1WITHECDSA // SHA224WITHECDSA // SHA256WITHECDSA // SHA384WITHECDSA // SHA512WITHECDSA Org.BouncyCastle.Crypto.ISignatureFactory signatureFactory = new Org.BouncyCastle.Crypto.Operators.Asn1SignatureFactory("SHA512WITHRSA", keypair.Private, random) ; var gen = new Org.BouncyCastle.X509.X509V3CertificateGenerator(); var CN = new Org.BouncyCastle.Asn1.X509.X509Name("CN=" + certName); var SN = Org.BouncyCastle.Math.BigInteger.ProbablePrime(120, new Random()); gen.SetSerialNumber(SN); gen.SetSubjectDN(CN); gen.SetIssuerDN(CN); gen.SetNotAfter(DateTime.Now.AddYears(1)); gen.SetNotBefore(DateTime.Now.Subtract(new TimeSpan(7, 0, 0, 0))); gen.SetPublicKey(keypair.Public); // -- Are these necessary ? // public static readonly DerObjectIdentifier AuthorityKeyIdentifier = new DerObjectIdentifier("2.5.29.35"); // OID value: 2.5.29.35 // OID description: id-ce-authorityKeyIdentifier // This extension may be used either as a certificate or CRL extension. // It identifies the public key to be used to verify the signature on this certificate or CRL. // It enables distinct keys used by the same CA to be distinguished (e.g., as key updating occurs). // http://stackoverflow.com/questions/14930381/generating-x509-certificate-using-bouncy-castle-java gen.AddExtension( Org.BouncyCastle.Asn1.X509.X509Extensions.AuthorityKeyIdentifier.Id, false, new Org.BouncyCastle.Asn1.X509.AuthorityKeyIdentifier( Org.BouncyCastle.X509.SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(keypair.Public), new Org.BouncyCastle.Asn1.X509.GeneralNames(new Org.BouncyCastle.Asn1.X509.GeneralName(CN)), SN )); // OID value: 1.3.6.1.5.5.7.3.1 // OID description: Indicates that a certificate can be used as an SSL server certificate. gen.AddExtension( Org.BouncyCastle.Asn1.X509.X509Extensions.ExtendedKeyUsage.Id, false, new Org.BouncyCastle.Asn1.X509.ExtendedKeyUsage(new ArrayList() { new Org.BouncyCastle.Asn1.DerObjectIdentifier("1.3.6.1.5.5.7.3.1") })); // -- End are these necessary ? Org.BouncyCastle.X509.X509Certificate bouncyCert = gen.Generate(signatureFactory); byte[] ba = bouncyCert.GetEncoded(); System.Security.Cryptography.X509Certificates.X509Certificate2 msCert = new System.Security.Cryptography.X509Certificates.X509Certificate2(ba); return(msCert); }
} // End Function GenerateRootCertificate // SHA512WITHRSA // SHA512WITHRSAANDMGF1 // RIPEMD256WITHRSA // SHA512WITHDSA // SHA512WITHECDSA // GOST3411WITHECGOST3410 private static Org.BouncyCastle.X509.X509Certificate GenerateCertificate( Org.BouncyCastle.Asn1.X509.X509Name issuer, Org.BouncyCastle.Asn1.X509.X509Name subject, Org.BouncyCastle.Crypto.AsymmetricKeyParameter issuerPrivate, Org.BouncyCastle.Crypto.AsymmetricKeyParameter subjectPublic, Org.BouncyCastle.Security.SecureRandom secureRandom ) { Org.BouncyCastle.Crypto.ISignatureFactory signatureFactory; if (issuerPrivate is Org.BouncyCastle.Crypto.Parameters.ECPrivateKeyParameters) { // System.Collections.IEnumerable names = Org.BouncyCastle.Crypto.Operators.Asn1SignatureFactory.SignatureAlgNames; // System.Console.WriteLine(names); // string x9 = Org.BouncyCastle.Asn1.X9.X9ObjectIdentifiers.ECDsaWithSha256.ToString(); // System.Console.WriteLine(x9); // Org.BouncyCastle.Asn1.X9.X9ObjectIdentifiers.ECDsaWithSha512 signatureFactory = new Org.BouncyCastle.Crypto.Operators.Asn1SignatureFactory( Org.BouncyCastle.Asn1.X9.X9ObjectIdentifiers.ECDsaWithSha256.ToString(), issuerPrivate); } else { // Org.BouncyCastle.Asn1.Pkcs.PkcsObjectIdentifiers.Sha512WithRsaEncryption signatureFactory = new Org.BouncyCastle.Crypto.Operators.Asn1SignatureFactory( Org.BouncyCastle.Asn1.Pkcs.PkcsObjectIdentifiers.Sha256WithRsaEncryption.ToString(), issuerPrivate); } Org.BouncyCastle.Math.BigInteger serialNumber = Org.BouncyCastle.Utilities.BigIntegers.CreateRandomInRange( Org.BouncyCastle.Math.BigInteger.One, Org.BouncyCastle.Math.BigInteger.ValueOf(System.Int64.MaxValue), secureRandom ); // Org.BouncyCastle.Asn1.X509.X509Name subjectDN = new Org.BouncyCastle.Asn1.X509.X509Name("CN=" + commonNameValue); Org.BouncyCastle.X509.X509V3CertificateGenerator certGenerator = new Org.BouncyCastle.X509.X509V3CertificateGenerator(); certGenerator.SetIssuerDN(issuer); certGenerator.SetSubjectDN(subject); // The certificate needs a serial number. // This is used for revocation, and usually should be an incrementing index // (which makes it easier to revoke a range of certificates). // Since we don’t have anywhere to store the incrementing index, we can just use a random number. // certGenerator.SetSerialNumber(serialNumber); certGenerator.SetSerialNumber(Org.BouncyCastle.Math.BigInteger.ValueOf(1)); certGenerator.SetNotAfter(System.DateTime.UtcNow.AddHours(1)); certGenerator.SetNotBefore(System.DateTime.UtcNow); certGenerator.SetPublicKey(subjectPublic); // https://www.programcreek.com/java-api-examples/?class=org.bouncycastle.x509.X509V3CertificateGenerator&method=setSubjectDN // certGenerator.AddExtension(Org.BouncyCastle.Asn1.X509.X509Name.C.Id, true, new X509Name("CH")); // https://en.wikipedia.org/wiki/Subject_Alternative_Name // byte[] subjectAltName = new GeneralNames(new GeneralName(GeneralName.DnsName, "localhost")).GetDerEncoded(); // certGenerator.AddExtension(Org.BouncyCastle.Asn1.X509.X509Extensions.SubjectAlternativeName, false, subjectAltName); /* * // https://www.programcreek.com/java-api-examples/?api=org.bouncycastle.cert.X509v3CertificateBuilder * Org.BouncyCastle.Asn1.DerSequence subjectAlternativeNames = * new Org.BouncyCastle.Asn1.DerSequence( * new Org.BouncyCastle.Asn1.Asn1Encodable[] { * new Org.BouncyCastle.Asn1.X509.GeneralName(Org.BouncyCastle.Asn1.X509.GeneralName.DnsName, "localhost"), * new Org.BouncyCastle.Asn1.X509.GeneralName(Org.BouncyCastle.Asn1.X509.GeneralName.DnsName, System.Environment.MachineName), * new Org.BouncyCastle.Asn1.X509.GeneralName(Org.BouncyCastle.Asn1.X509.GeneralName.DnsName, "127.0.0.1") * }); * * * certGenerator.AddExtension( * Org.BouncyCastle.Asn1.X509.X509Extensions.SubjectAlternativeName * , false * , subjectAlternativeNames * ); */ // https://security.stackexchange.com/questions/169217/certificate-chain-is-broken // certGenerator.AddExtension(Org.BouncyCastle.Asn1.X509.X509Extensions.BasicConstraints.Id, true, new Org.BouncyCastle.Asn1.X509.BasicConstraints(3)); // Key Usage certGenerator.AddExtension(Org.BouncyCastle.Asn1.X509.X509Extensions.KeyUsage, true , new Org.BouncyCastle.Asn1.X509.KeyUsage( Org.BouncyCastle.Asn1.X509.KeyUsage.DigitalSignature | Org.BouncyCastle.Asn1.X509.KeyUsage.KeyEncipherment | Org.BouncyCastle.Asn1.X509.KeyUsage.DataEncipherment | Org.BouncyCastle.Asn1.X509.KeyUsage.KeyCertSign | Org.BouncyCastle.Asn1.X509.KeyUsage.KeyAgreement | Org.BouncyCastle.Asn1.X509.KeyUsage.NonRepudiation | Org.BouncyCastle.Asn1.X509.KeyUsage.CrlSign ) ); certGenerator.AddExtension(Org.BouncyCastle.Asn1.X509.X509Extensions.ExtendedKeyUsage.Id, true , new Org.BouncyCastle.Asn1.X509.ExtendedKeyUsage(new[] { Org.BouncyCastle.Asn1.X509.KeyPurposeID.IdKPClientAuth , Org.BouncyCastle.Asn1.X509.KeyPurposeID.IdKPServerAuth }) ); return(certGenerator.Generate(signatureFactory)); } // End Function GenerateCertificate
} // End Function GenerateSslCertificate public static Org.BouncyCastle.X509.X509Certificate GenerateRootCertificate( CertificateInfo certificateInfo , Org.BouncyCastle.Security.SecureRandom secureRandom ) { // The Certificate Generator Org.BouncyCastle.X509.X509V3CertificateGenerator certificateGenerator = new Org.BouncyCastle.X509.X509V3CertificateGenerator(); Org.BouncyCastle.Asn1.X509.X509Name subjectDn = certificateInfo.Subject; Org.BouncyCastle.Asn1.X509.X509Name issuerDn = certificateInfo.Subject; certificateGenerator.SetSubjectDN(issuerDn); certificateGenerator.SetIssuerDN(issuerDn); certificateGenerator.SetNotBefore(certificateInfo.ValidFrom); certificateGenerator.SetNotAfter(certificateInfo.ValidTo); Org.BouncyCastle.Crypto.AsymmetricKeyParameter publicKey = KeyImportExport.ReadPublicKey(certificateInfo.SubjectKeyPair.PublicKey); Org.BouncyCastle.Crypto.AsymmetricKeyParameter privateKey = KeyImportExport.ReadPrivateKey(certificateInfo.SubjectKeyPair.PrivateKey); AddExtensions(certificateGenerator, certificateInfo); Org.BouncyCastle.Crypto.ISignatureFactory signatureFactory = CreateSignatureFactory(privateKey); certificateGenerator.SetPublicKey(publicKey); // Serial Number Org.BouncyCastle.Math.BigInteger serialNumber = Org.BouncyCastle.Utilities.BigIntegers.CreateRandomInRange( Org.BouncyCastle.Math.BigInteger.One , Org.BouncyCastle.Math.BigInteger.ValueOf(long.MaxValue) , secureRandom ); certificateGenerator.SetSerialNumber(serialNumber); certificateGenerator.AddExtension(Org.BouncyCastle.Asn1.X509.X509Extensions.KeyUsage, true , new Org.BouncyCastle.Asn1.X509.KeyUsage( Org.BouncyCastle.Asn1.X509.KeyUsage.DigitalSignature | Org.BouncyCastle.Asn1.X509.KeyUsage.KeyCertSign | Org.BouncyCastle.Asn1.X509.KeyUsage.CrlSign | Org.BouncyCastle.Asn1.X509.KeyUsage.KeyEncipherment | Org.BouncyCastle.Asn1.X509.KeyUsage.DataEncipherment | Org.BouncyCastle.Asn1.X509.KeyUsage.KeyAgreement | Org.BouncyCastle.Asn1.X509.KeyUsage.NonRepudiation ) ); Org.BouncyCastle.Asn1.X509.AuthorityKeyIdentifier authorityKeyIdentifierExtension = new Org.BouncyCastle.Asn1.X509.AuthorityKeyIdentifier( Org.BouncyCastle.X509.SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKey) ); Org.BouncyCastle.Asn1.X509.SubjectKeyIdentifier subjectKeyIdentifierExtension = new Org.BouncyCastle.Asn1.X509.SubjectKeyIdentifier( Org.BouncyCastle.X509.SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKey) ); certificateGenerator.AddExtension( Org.BouncyCastle.Asn1.X509.X509Extensions.SubjectKeyIdentifier.Id , false , subjectKeyIdentifierExtension ); certificateGenerator.AddExtension( Org.BouncyCastle.Asn1.X509.X509Extensions.AuthorityKeyIdentifier.Id , false , authorityKeyIdentifierExtension ); // Set certificate intended purposes to only Server Authentication //certificateGenerator.AddExtension(Org.BouncyCastle.Asn1.X509.X509Extensions.ExtendedKeyUsage.Id // , true // , new Org.BouncyCastle.Asn1.X509.ExtendedKeyUsage(Org.BouncyCastle.Asn1.X509.KeyPurposeID.IdKPServerAuth) //); certificateGenerator.AddExtension(Org.BouncyCastle.Asn1.X509.X509Extensions.ExtendedKeyUsage.Id, true , new Org.BouncyCastle.Asn1.X509.ExtendedKeyUsage(new[] { Org.BouncyCastle.Asn1.X509.KeyPurposeID.IdKPClientAuth, Org.BouncyCastle.Asn1.X509.KeyPurposeID.IdKPServerAuth }) ); // Only if we generate a root-Certificate certificateGenerator.AddExtension(Org.BouncyCastle.Asn1.X509.X509Extensions.BasicConstraints.Id , true , new Org.BouncyCastle.Asn1.X509.BasicConstraints(true) ); return(certificateGenerator.Generate(signatureFactory)); } // End Function GenerateRootCertificate
} // End Sub AddExtensions public static Org.BouncyCastle.X509.X509Certificate GenerateSslCertificate( CertificateInfo certificateInfo , Org.BouncyCastle.Security.SecureRandom secureRandom , Org.BouncyCastle.X509.X509Certificate rootCertificate ) { // The Certificate Generator Org.BouncyCastle.X509.X509V3CertificateGenerator certificateGenerator = new Org.BouncyCastle.X509.X509V3CertificateGenerator(); certificateGenerator.SetSubjectDN(certificateInfo.Subject); certificateGenerator.SetIssuerDN(rootCertificate.IssuerDN); Org.BouncyCastle.Math.BigInteger serialNumber = Org.BouncyCastle.Utilities.BigIntegers.CreateRandomInRange( Org.BouncyCastle.Math.BigInteger.One, Org.BouncyCastle.Math.BigInteger.ValueOf(System.Int64.MaxValue), secureRandom ); certificateGenerator.SetSerialNumber(Org.BouncyCastle.Math.BigInteger.ValueOf(1)); certificateGenerator.SetNotBefore(certificateInfo.ValidFrom); certificateGenerator.SetNotAfter(certificateInfo.ValidTo); Org.BouncyCastle.Crypto.AsymmetricKeyParameter subjectPublicKey = KeyImportExport.ReadPublicKey(certificateInfo.SubjectKeyPair.PublicKey); Org.BouncyCastle.Crypto.AsymmetricKeyParameter issuerPrivateKey = KeyImportExport.ReadPrivateKey(certificateInfo.IssuerKeyPair.PrivateKey); certificateGenerator.AddExtension(Org.BouncyCastle.Asn1.X509.X509Extensions.SubjectAlternativeName.Id , false , certificateInfo.SubjectAlternativeNames ); certificateGenerator.SetPublicKey(subjectPublicKey); Org.BouncyCastle.Asn1.X509.SubjectKeyIdentifier subjectKeyIdentifierExtension = new Org.BouncyCastle.Asn1.X509.SubjectKeyIdentifier( Org.BouncyCastle.X509.SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(subjectPublicKey) ); certificateGenerator.AddExtension( Org.BouncyCastle.Asn1.X509.X509Extensions.SubjectKeyIdentifier.Id , false , subjectKeyIdentifierExtension ); certificateGenerator.AddExtension(Org.BouncyCastle.Asn1.X509.X509Extensions.ExtendedKeyUsage.Id, false, new Org.BouncyCastle.Asn1.X509.ExtendedKeyUsage(Org.BouncyCastle.Asn1.X509.KeyPurposeID.IdKPServerAuth) ); // rootCertificate.GetPublicKey(): // rootCertificate.GetEncoded() // System.Security.Cryptography.X509Certificates.X509Certificate2 srp = // new System.Security.Cryptography.X509Certificates.X509Certificate2(rootCertificate.GetEncoded()); // srp.PrivateKey // srp.HasPrivateKey // Org.BouncyCastle.Crypto.AsymmetricKeyParameter Akp = Org.BouncyCastle.Security.DotNetUtilities.GetKeyPair(srp.PrivateKey).Private; // Org.BouncyCastle.Crypto.IDigest algorithm = Org.BouncyCastle.Security.DigestUtilities.GetDigest(rootCertificate.SigAlgOid); // var signature = new X509Certificate2Signature(cert, algorithm); // rootCertificate.SigAlgOid // rootCertificate.GetSignature(); // srp.GetRawCertData() // X509CertificateParser certParser = new X509CertificateParser(); // X509Certificate privateCertBouncy = certParser.ReadCertificate(mycert.GetRawCertData()); // AsymmetricKeyParameter pubKey = privateCertBouncy.GetPublicKey(); AddExtensions(certificateGenerator, certificateInfo); Org.BouncyCastle.Crypto.ISignatureFactory signatureFactory = CreateSignatureFactory(issuerPrivateKey); return(certificateGenerator.Generate(signatureFactory)); } // End Function GenerateSslCertificate
} // End Sub AddExtensions public static Org.BouncyCastle.X509.X509Certificate GenerateSslCertificate( CertificateInfo certificateInfo1 , Org.BouncyCastle.Crypto.AsymmetricKeyParameter subjectPublicKey , Org.BouncyCastle.Crypto.AsymmetricKeyParameter issuerPrivateKey , Org.BouncyCastle.X509.X509Certificate rootCertificate , Org.BouncyCastle.Security.SecureRandom secureRandom ) { // The Certificate Generator Org.BouncyCastle.X509.X509V3CertificateGenerator certificateGenerator = new Org.BouncyCastle.X509.X509V3CertificateGenerator(); certificateGenerator.SetSubjectDN(certificateInfo1.Subject); certificateGenerator.SetIssuerDN(rootCertificate.IssuerDN); Org.BouncyCastle.Math.BigInteger serialNumber = Org.BouncyCastle.Utilities.BigIntegers.CreateRandomInRange( Org.BouncyCastle.Math.BigInteger.One, Org.BouncyCastle.Math.BigInteger.ValueOf(System.Int64.MaxValue), secureRandom ); certificateGenerator.SetSerialNumber(Org.BouncyCastle.Math.BigInteger.ValueOf(1)); certificateGenerator.SetNotBefore(certificateInfo1.ValidFrom); certificateGenerator.SetNotAfter(certificateInfo1.ValidTo); certificateGenerator.AddExtension(Org.BouncyCastle.Asn1.X509.X509Extensions.SubjectAlternativeName.Id , false , certificateInfo1.SubjectAlternativeNames ); certificateGenerator.SetPublicKey(subjectPublicKey); Org.BouncyCastle.Asn1.X509.SubjectKeyIdentifier subjectKeyIdentifierExtension = new Org.BouncyCastle.Asn1.X509.SubjectKeyIdentifier( Org.BouncyCastle.X509.SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(subjectPublicKey) ); certificateGenerator.AddExtension( Org.BouncyCastle.Asn1.X509.X509Extensions.SubjectKeyIdentifier.Id , false , subjectKeyIdentifierExtension ); certificateGenerator.AddExtension(Org.BouncyCastle.Asn1.X509.X509Extensions.ExtendedKeyUsage.Id, false, new Org.BouncyCastle.Asn1.X509.ExtendedKeyUsage(Org.BouncyCastle.Asn1.X509.KeyPurposeID.IdKPServerAuth) ); AddExtensions(certificateGenerator, certificateInfo1); Org.BouncyCastle.Crypto.ISignatureFactory signatureFactory = CreateSignatureFactory(issuerPrivateKey); return(certificateGenerator.Generate(signatureFactory)); } // End Function GenerateSslCertificate