Пример #1
0
        } // End Sub AddExtensions 


        public static Org.BouncyCastle.X509.X509Certificate GenerateSslCertificate(
            CertificateInfo certificateInfo
          , Org.BouncyCastle.Security.SecureRandom secureRandom
          , Org.BouncyCastle.X509.X509Certificate rootCertificate
      )
        {
            Org.BouncyCastle.Crypto.AsymmetricKeyParameter subjectPublicKey =
           KeyImportExport.ReadPublicKey(certificateInfo.SubjectKeyPair.PublicKey);

            Org.BouncyCastle.Crypto.AsymmetricKeyParameter issuerPrivateKey =
                KeyImportExport.ReadPrivateKey(certificateInfo.IssuerKeyPair.PrivateKey);

            return GenerateSslCertificate(certificateInfo, subjectPublicKey, issuerPrivateKey, rootCertificate, secureRandom);
        }
Пример #2
0
        } // End Sub SelfSignSslCertificate

        // https://stackoverflow.com/questions/51703109/nginx-the-ssl-directive-is-deprecated-use-the-listen-ssl
        public static Org.BouncyCastle.X509.X509Certificate GenerateRootCertificate()
        {
            string countryIso2Characters = "EA";
            string stateOrProvince       = "Europe";
            string localityOrCity        = "NeutralZone";
            string companyName           = "Skynet Earth Inc.";
            string division   = "Skynet mbH";
            string domainName = "Skynet";
            string email      = "*****@*****.**";


            Org.BouncyCastle.Security.SecureRandom sr = new Org.BouncyCastle.Security.SecureRandom(NonBackdooredPrng.Create());

            Org.BouncyCastle.X509.X509Certificate caRoot = null;
            Org.BouncyCastle.X509.X509Certificate caSsl  = null;

            // string curveName = "curve25519"; curveName = "secp256k1";


            CertificateInfo caCertInfo = new CertificateInfo(
                countryIso2Characters, stateOrProvince
                , localityOrCity, companyName
                , division, domainName, email
                , System.DateTime.UtcNow
                , System.DateTime.UtcNow.AddYears(5)
                );


            // Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair kp1 = KeyGenerator.GenerateEcKeyPair(curveName, sr);
            Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair kp1 = KeyGenerator.GenerateRsaKeyPair(2048, sr);
            // Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair kp1 = KeyGenerator.GenerateDsaKeyPair(1024, sr);
            // Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair kp1 = KeyGenerator.GenerateDHKeyPair(1024, sr);

            // kp1 = KeyGenerator.GenerateGhostKeyPair(4096, s_secureRandom.Value);

            caCertInfo.SubjectKeyPair = KeyImportExport.GetPemKeyPair(kp1);
            caCertInfo.IssuerKeyPair  = KeyImportExport.GetPemKeyPair(kp1);


            caRoot = CerGenerator.GenerateRootCertificate(caCertInfo, sr);


            PfxGenerator.CreatePfxFile(@"ca.pfx", caRoot, kp1.Private, null);
            CerGenerator.WritePrivatePublicKey("issuer", caCertInfo.IssuerKeyPair);

            return(caRoot);
        } // End Sub GenerateRootCertificate
Пример #3
0
        } // End Sub Test

        public static void SelfSignSslCertificate(Org.BouncyCastle.Security.SecureRandom random, Org.BouncyCastle.X509.X509Certificate caRoot, Org.BouncyCastle.Crypto.AsymmetricKeyParameter rootCertPrivateKey) // PrivatePublicPemKeyPair subjectKeyPair)
        {
            Org.BouncyCastle.X509.X509Certificate caSsl = null;

            string countryIso2Characters = "GA";
            string stateOrProvince       = "Aremorica";
            string localityOrCity        = "Erquy, Bretagne";
            string companyName           = "Coopérative Ménhir Obelix Gmbh & Co. KGaA";
            string division   = "NT (Neanderthal Technology)";
            string domainName = "localhost";

            domainName = "*.sql.guru";
            domainName = "localhost";
            string email = "webmaster@localhost";


            CertificateInfo ci = new CertificateInfo(
                countryIso2Characters, stateOrProvince
                , localityOrCity, companyName
                , division, domainName, email
                , System.DateTime.UtcNow
                , System.DateTime.UtcNow.AddYears(5)
                );

            ci.AddAlternativeNames("localhost", System.Environment.MachineName, "127.0.0.1",
                                   "sql.guru", "*.sql.guru");

            // Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair kp1 = KeyGenerator.GenerateEcKeyPair(curveName, random);
            Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair kp1 = KeyGenerator.GenerateRsaKeyPair(2048, random);
            // Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair kp1 = KeyGenerator.GenerateDsaKeyPair(1024, random);
            // Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair kp1 = KeyGenerator.GenerateDHKeyPair(1024, random);



            ci.SubjectKeyPair = KeyImportExport.GetPemKeyPair(kp1);
            // ci.IssuerKeyPair.PrivateKey = rootCert.PrivateKey;

            // caSsl = CerGenerator.GenerateSslCertificate(ci, random, caRoot);

            Org.BouncyCastle.Crypto.AsymmetricKeyParameter subjectPublicKey = null;
            // This is the private key of the root certificate
            Org.BouncyCastle.Crypto.AsymmetricKeyParameter issuerPrivateKey = null;

            caSsl = CerGenerator.GenerateSslCertificate(
                ci
                , subjectPublicKey
                , issuerPrivateKey
                , caRoot
                , random
                );


            CertificateToDerPem(caSsl);



            // Just to clarify, an X.509 certificate does not contain the private key
            // The whole point of using certificates is to send them more or less openly,
            // without sending the private key, which must be kept secret.
            // An X509Certificate2 object may have a private key associated with it (via its PrivateKey property),
            // but that's only a convenience as part of the design of this class.
            // System.Security.Cryptography.X509Certificates.X509Certificate2 = new System.Security.Cryptography.X509Certificates.X509Certificate2(caRoot.GetEncoded());
            // System.Console.WriteLine(cc.PublicKey);
            // System.Console.WriteLine(cc.PrivateKey);

            bool val = CerGenerator.ValidateSelfSignedCert(caSsl, caRoot.GetPublicKey());

            System.Console.WriteLine(val);

            PfxGenerator.CreatePfxFile(@"obelix.pfx", caSsl, kp1.Private, "");
            CerGenerator.WritePrivatePublicKey("obelix", ci.SubjectKeyPair);


            CerGenerator.WriteCerAndCrt(@"ca", caRoot);
            CerGenerator.WriteCerAndCrt(@"obelix", caSsl);
        } // End Sub SelfSignSslCertificate
Пример #4
0
        }         // End Sub WriteCerAndCrt

        public static void Test()
        {
            Org.BouncyCastle.Asn1.X509.X509Name caName      = new Org.BouncyCastle.Asn1.X509.X509Name("CN=TestCA");
            Org.BouncyCastle.Asn1.X509.X509Name eeName      = new Org.BouncyCastle.Asn1.X509.X509Name("CN=TestEE");
            Org.BouncyCastle.Asn1.X509.X509Name eeName25519 = new Org.BouncyCastle.Asn1.X509.X509Name("CN=TestEE25519");

            string countryIso2Characters = "EA";
            string stateOrProvince       = "ERA";
            string localityOrCity        = "NeutralZone";
            string companyName           = "Skynet Earth Inc.";
            string division   = "Skynet mbH";
            string domainName = "sky.net";
            string email      = "*****@*****.**";


            Org.BouncyCastle.Asn1.X509.X509Name subj = CertificateInfo.CreateSubject(
                countryIso2Characters, stateOrProvince
                , localityOrCity, companyName
                , division, domainName, email);

            System.Console.WriteLine(subj);


            Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair caKey25519 = KeyGenerator.GenerateEcKeyPair("curve25519", s_secureRandom.Value);
            Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair caKey      = KeyGenerator.GenerateEcKeyPair("secp256r1", s_secureRandom.Value);
            Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair eeKey      = KeyGenerator.GenerateRsaKeyPair(2048, s_secureRandom.Value);


            string publicKey = null;

            // id_rsa.pub
            using (System.IO.TextWriter textWriter = new System.IO.StringWriter())
            {
                Org.BouncyCastle.OpenSsl.PemWriter pemWriter = new Org.BouncyCastle.OpenSsl.PemWriter(textWriter);
                pemWriter.WriteObject(eeKey);
                pemWriter.Writer.Flush();

                publicKey = textWriter.ToString();
            } // End Using textWriter

            System.Console.WriteLine(publicKey);


            // https://social.msdn.microsoft.com/Forums/vstudio/de-DE/8d49a681-22c6-417f-af3c-8daebd6f10dd/signierung-eines-hashs-mit-ellipticcurve-crypto?forum=visualcsharpde
            // https://stackoverflow.com/questions/22963581/reading-elliptic-curve-private-key-from-file-with-bouncycastle/41947163
            // PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(pkcs8key);

            // The EC PARAMETERS block in your file is an accident of the way openssl ecparam - genkey works by default;
            // it is not needed or used as part of the actual key and you can omit it by specifying - noout
            // which is admittedly somewhat unobvious.
            // The actual key structure('hidden' in the base64/ DER data) for EC(DSA / DH)
            // does contain some parameter info which RSA doesn't but DSA does.
            PrivatePublicPemKeyPair keyPair = KeyImportExport.GetPemKeyPair(caKey25519);

            // PrivatePublicPemKeyPair keyPair = PrivatePublicPemKeyPair.ImportFrom("", "");


            Org.BouncyCastle.X509.X509Certificate caCert      = GenerateCertificate(caName, caName, caKey.Private, caKey.Public, s_secureRandom.Value);
            Org.BouncyCastle.X509.X509Certificate eeCert      = GenerateCertificate(caName, eeName, caKey.Private, eeKey.Public, s_secureRandom.Value);
            Org.BouncyCastle.X509.X509Certificate ee25519Cert = GenerateCertificate(caName, eeName25519, caKey25519.Private, caKey25519.Public, s_secureRandom.Value);


            bool caOk    = ValidateSelfSignedCert(caCert, caKey.Public);
            bool eeOk    = ValidateSelfSignedCert(eeCert, caKey.Public);
            bool ee25519 = ValidateSelfSignedCert(eeCert, caKey.Public);

            PfxGenerator.CreatePfxFile("example.pfx", caCert, caKey.Private, null);

            // System.IO.File.WriteAllBytes("fileName", caCert.Export(X509ContentType.Pkcs12, PfxPassword));

            // https://info.ssl.com/how-to-der-vs-crt-vs-cer-vs-pem-certificates-and-how-to-conver-them/
            // The file extensions .CRT and .CER are interchangeable.
            // If your server requires that you use the .CER file extension, you can change the extension
            // http://www.networksolutions.com/support/what-is-the-difference-between-a-crt-and-a-cer-file/
            // https://stackoverflow.com/questions/642284/apache-with-ssl-how-to-convert-cer-to-crt-certificates
            // File extensions for cryptographic certificates aren't really as standardized as you'd expect.
            // Windows by default treats double - clicking a.crt file as a request to import the certificate
            // So, they're different in that sense, at least, that Windows has some inherent different meaning
            // for what happens when you double click each type of file.

            // One is a "binary" X.509 encoding, and the other is a "text" base64 encoding that usually starts with "-----BEGIN CERTIFICATE-----".
            // into the Windows Root Certificate store, but treats a.cer file as a request just to view the certificate.
            // CER is an X.509 certificate in binary form, DER encoded
            // CRT is a binary X.509 certificate, encapsulated in text (base-64) encoding
            // Most systems accept both formats, but if you need to you can convert one to the other via openssl
            // Certificate file should be PEM-encoded X.509 Certificate file:
            // openssl x509 -inform DER -in certificate.cer -out certificate.pem
            using (System.IO.Stream f = System.IO.File.Open("ca.cer", System.IO.FileMode.Create))
            {
                byte[] buf = caCert.GetEncoded();
                f.Write(buf, 0, buf.Length);
                f.Flush();
            }

            using (System.IO.Stream fs = System.IO.File.Open("ee.cer", System.IO.FileMode.Create))
            {
                byte[] buf = eeCert.GetEncoded();
                fs.Write(buf, 0, buf.Length);
                fs.Flush();
            } // End Using fs

            using (System.IO.Stream fs = System.IO.File.Open("ee25519.cer", System.IO.FileMode.Create))
            {
                byte[] buf = ee25519Cert.GetEncoded();
                fs.Write(buf, 0, buf.Length);
                fs.Flush();
            } // End Using fs

            // new System.Text.ASCIIEncoding(false)
            // new System.Text.UTF8Encoding(false)
            using (System.IO.Stream fs = System.IO.File.Open("ee.crt", System.IO.FileMode.Create))
            {
                using (System.IO.StreamWriter sw = new System.IO.StreamWriter(fs, System.Text.Encoding.ASCII))
                {
                    byte[] buf = eeCert.GetEncoded();
                    string pem = ToPem(buf);

                    sw.Write(pem);
                } // End Using sw
            }     // End Using fs

            using (System.IO.Stream fs = System.IO.File.Open("ee25519.crt", System.IO.FileMode.Create))
            {
                using (System.IO.StreamWriter sw = new System.IO.StreamWriter(fs, System.Text.Encoding.ASCII))
                {
                    byte[] buf = ee25519Cert.GetEncoded();
                    string pem = ToPem(buf);

                    sw.Write(pem);
                } // End Using sw
            }     // End Using fs

            Org.BouncyCastle.Asn1.X509.X509Name subject = eeName25519;
        } // End Sub Test
Пример #5
0
        } // End Function ValidateSelfSignedCert

        // https://stackoverflow.com/questions/51703109/nginx-the-ssl-directive-is-deprecated-use-the-listen-ssl
        public static void Test2()
        {
            Org.BouncyCastle.X509.X509Certificate caRoot = null;
            Org.BouncyCastle.X509.X509Certificate caSsl  = null;
            CertificateInfo caCertInfo = null;
            string          curveName  = "curve25519";

            curveName = "secp256k1";


            {
                string countryIso2Characters = "EA";
                string stateOrProvince       = "Europe";
                string localityOrCity        = "NeutralZone";
                string companyName           = "Skynet Earth Inc.";
                string division   = "Skynet mbH";
                string domainName = "Skynet";
                string email      = "*****@*****.**";


                caCertInfo = new CertificateInfo(
                    countryIso2Characters, stateOrProvince
                    , localityOrCity, companyName
                    , division, domainName, email
                    , System.DateTime.UtcNow
                    , System.DateTime.UtcNow.AddYears(5)
                    );

                // Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair kp1 = KeyGenerator.GenerateEcKeyPair(curveName, s_secureRandom.Value);
                Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair kp1 = KeyGenerator.GenerateRsaKeyPair(2048, s_secureRandom.Value);
                // Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair kp1 = KeyGenerator.GenerateDsaKeyPair(1024, s_secureRandom.Value);
                // Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair kp1 = KeyGenerator.GenerateDHKeyPair(1024, s_secureRandom.Value);

                // kp1 = KeyGenerator.GenerateGhostKeyPair(4096, s_secureRandom.Value);

                caCertInfo.SubjectKeyPair = KeyImportExport.GetPemKeyPair(kp1);
                caCertInfo.IssuerKeyPair  = KeyImportExport.GetPemKeyPair(kp1);

                caRoot = GenerateRootCertificate(caCertInfo, s_secureRandom.Value);

                PfxGenerator.CreatePfxFile(@"ca.pfx", caRoot, kp1.Private, null);
                WritePrivatePublicKey("issuer", caCertInfo.IssuerKeyPair);
            }


            {
                string countryIso2Characters = "GA";
                string stateOrProvince       = "Aremorica";
                string localityOrCity        = "Erquy, Bretagne";
                string companyName           = "Coopérative Ménhir Obelix Gmbh & Co. KGaA";
                string division   = "NT (Neanderthal Technology)";
                string domainName = "localhost";
                domainName = "*.sql.guru";
                domainName = "localhost";
                string email = "webmaster@localhost";


                CertificateInfo ci = new CertificateInfo(
                    countryIso2Characters, stateOrProvince
                    , localityOrCity, companyName
                    , division, domainName, email
                    , System.DateTime.UtcNow
                    , System.DateTime.UtcNow.AddYears(5)
                    );

                ci.AddAlternativeNames("localhost", System.Environment.MachineName, "127.0.0.1",
                                       "sql.guru", "*.sql.guru");

                // Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair kp1 = KeyGenerator.GenerateEcKeyPair(curveName, s_secureRandom.Value);
                Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair kp1 = KeyGenerator.GenerateRsaKeyPair(2048, s_secureRandom.Value);
                // Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair kp1 = KeyGenerator.GenerateDsaKeyPair(1024, s_secureRandom.Value);
                // Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair kp1 = KeyGenerator.GenerateDHKeyPair(1024, s_secureRandom.Value);



                ci.SubjectKeyPair = KeyImportExport.GetPemKeyPair(kp1);
                ci.IssuerKeyPair  = caCertInfo.SubjectKeyPair;

                caSsl = GenerateSslCertificate(ci, s_secureRandom.Value, caRoot);

                // Just to clarify, an X.509 certificate does not contain the private key
                // The whole point of using certificates is to send them more or less openly,
                // without sending the private key, which must be kept secret.
                // An X509Certificate2 object may have a private key associated with it (via its PrivateKey property),
                // but that's only a convenience as part of the design of this class.
                // var cc = new System.Security.Cryptography.X509Certificates.X509Certificate2(caRoot.GetEncoded());
                // System.Console.WriteLine(cc.PublicKey);
                // System.Console.WriteLine(cc.PrivateKey);

                bool val = ValidateSelfSignedCert(caSsl, caRoot.GetPublicKey());
                System.Console.WriteLine(val);

                PfxGenerator.CreatePfxFile(@"obelix.pfx", caSsl, kp1.Private, "");
                WritePrivatePublicKey("obelix", ci.SubjectKeyPair);
            }

            WriteCerAndCrt(@"ca", caRoot);
            WriteCerAndCrt(@"obelix", caSsl);
        } // End Sub Test2
Пример #6
0
        } // 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
Пример #7
0
        }     // 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