如何使用BouncyCastle生成根证书,然后使用由该根证书签名的站点证书?

我正在尝试构建一个使用带有SSL WebAPI的自托管服务,我需要能够自行生成要使用的SSL证书。 我希望能够从C#做到这一切。 我一直在玩BouncyCastle

我需要生成2个证书,一个根和一个站点证书。 然后我需要在Windows中将它们安装在正确的位置。

我无法弄清楚如何使我的第二个证书参考我的根ca. 我试过的所有东西都让我得到了一个不受信任的证书错误。 任何帮助,将不胜感激。

这就是我所做的(我正在使用DSA,但如果您使用的是RSA,只需更改密钥生成)。

 public void IssueClientFromCA() { // get CA string caCn = "MyCA CommonName"; Stream caCertFile = File.OpenRead(string.Format(@"{0}\{1}", _certificatesDir, "MyCAFile.pfx")); char[] caPass = "passwordForThePfx".ToCharArray(); Pkcs12Store store = new Pkcs12StoreBuilder().Build(); store.Load(caCertFile, caPass); var caCert = store.GetCertificate(caCn).Certificate; var caPrivKey = store.GetKey(caCn).Key; var clientCert = CertIssuer.GenerateDsaCertificateAsPkcs12( "My Client FriendlyName", "My Client SubjectName", "GT", new DateTime(2011,9,19), new DateTime(2014,9,18), "PFXPASS", caCert, caPrivKey); var saveAS = string.Format(@"{0}\{1}", _certificatesDir, "clientCertFile.pfx"); File.WriteAllBytes(saveAS, clientCert); } public static byte[] GenerateDsaCertificateAsPkcs12( string friendlyName, string subjectName, string country, DateTime validStartDate, DateTime validEndDate, string password, Org.BouncyCastle.X509.X509Certificate caCert, AsymmetricKeyParameter caPrivateKey) { var keys = GenerateDsaKeys(); #region build certificate var certGen = new X509V3CertificateGenerator(); // build name attributes var nameOids = new ArrayList(); nameOids.Add(Org.BouncyCastle.Asn1.X509.X509Name.CN); nameOids.Add(X509Name.O); nameOids.Add(X509Name.C); var nameValues = new ArrayList(); nameValues.Add(friendlyName); nameValues.Add(subjectName); nameValues.Add(country); var subjectDN = new X509Name(nameOids, nameValues); // certificate fields certGen.SetSerialNumber(BigInteger.ValueOf(1)); certGen.SetIssuerDN(caCert.SubjectDN); certGen.SetNotBefore(validStartDate); certGen.SetNotAfter(validEndDate); certGen.SetSubjectDN(subjectDN); certGen.SetPublicKey(keys.Public); certGen.SetSignatureAlgorithm("SHA1withDSA"); // extended information certGen.AddExtension(X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(caCert.GetPublicKey())); certGen.AddExtension(X509Extensions.SubjectKeyIdentifier, false, new SubjectKeyIdentifierStructure(keys.Public)); #endregion // generate x509 certificate var cert = certGen.Generate(caPrivateKey); //ert.Verify(caCert.GetPublicKey()); var chain = new Dictionary(); //chain.Add("CertiFirmas CA", caCert); var caCn = caCert.SubjectDN.GetValues(X509Name.CN)[0].ToString(); chain.Add(caCn, caCert); // store the file return GeneratePkcs12(keys, cert, friendlyName, password, chain); } private static byte[] GeneratePkcs12(AsymmetricCipherKeyPair keys, Org.BouncyCastle.X509.X509Certificate cert, string friendlyName, string password, Dictionary chain) { var chainCerts = new List(); // Create the PKCS12 store Pkcs12Store store = new Pkcs12StoreBuilder().Build(); // Add a Certificate entry X509CertificateEntry certEntry = new X509CertificateEntry(cert); store.SetCertificateEntry(friendlyName, certEntry); // use DN as the Alias. //chainCerts.Add(certEntry); // Add chain entries var additionalCertsAsBytes = new List(); if (chain != null && chain.Count > 0) { foreach (var additionalCert in chain) { additionalCertsAsBytes.Add(additionalCert.Value.GetEncoded()); } } if (chain != null && chain.Count > 0) { var addicionalCertsAsX09Chain = BuildCertificateChainBC(cert.GetEncoded(), additionalCertsAsBytes); foreach (var addCertAsX09 in addicionalCertsAsX09Chain) { chainCerts.Add(new X509CertificateEntry(addCertAsX09)); } } // Add a key entry AsymmetricKeyEntry keyEntry = new AsymmetricKeyEntry(keys.Private); // no chain store.SetKeyEntry(friendlyName, keyEntry, new X509CertificateEntry[] { certEntry }); using (var memoryStream = new MemoryStream()) { store.Save(memoryStream, password.ToCharArray(), new SecureRandom()); return memoryStream.ToArray(); } } 

一些缺失的方法:

 static IEnumerable BuildCertificateChainBC(byte[] primary, IEnumerable additional) { X509CertificateParser parser = new X509CertificateParser(); PkixCertPathBuilder builder = new PkixCertPathBuilder(); // Separate root from itermediate var intermediateCerts = new List(); HashSet rootCerts = new HashSet(); foreach (byte[] cert in additional) { var x509Cert = parser.ReadCertificate(cert); // Separate root and subordinate certificates if (x509Cert.IssuerDN.Equivalent(x509Cert.SubjectDN)) rootCerts.Add(new TrustAnchor(x509Cert, null)); else intermediateCerts.Add(x509Cert); } // Create chain for this certificate X509CertStoreSelector holder = new X509CertStoreSelector(); holder.Certificate = parser.ReadCertificate(primary); // WITHOUT THIS LINE BUILDER CANNOT BEGIN BUILDING THE CHAIN intermediateCerts.Add(holder.Certificate); PkixBuilderParameters builderParams = new PkixBuilderParameters(rootCerts, holder); builderParams.IsRevocationEnabled = false; X509CollectionStoreParameters intermediateStoreParameters = new X509CollectionStoreParameters(intermediateCerts); builderParams.AddStore(X509StoreFactory.Create( "Certificate/Collection", intermediateStoreParameters)); PkixCertPathBuilderResult result = builder.Build(builderParams); return result.CertPath.Certificates.Cast(); } private static AsymmetricCipherKeyPair GenerateDsaKeys() { DSACryptoServiceProvider DSA = new DSACryptoServiceProvider(); var dsaParams = DSA.ExportParameters(true); AsymmetricCipherKeyPair keys = DotNetUtilities.GetDsaKeyPair(dsaParams); return keys; } 

另外:您必须将CA证书安装到客户端计算机中的受信任CA存储中,以及客户端证书(它可能位于Personal或ThirdParty存储中)。