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

前端之家收集整理的这篇文章主要介绍了c# – 如何使用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,18),"PFXPASS",caCert,caPrivKey);

    var saveAS = string.Format(@"{0}\{1}","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,new SubjectKeyIdentifierStructure(keys.Public));
    #endregion

    // generate x509 certificate
    var cert = certGen.Generate(caPrivateKey);
    //ert.Verify(caCert.GetPublicKey());

    var chain = new Dictionary<string,Org.BouncyCastle.X509.X509Certificate>();
    //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,Dictionary<string,Org.BouncyCastle.X509.X509Certificate> chain)
{
    var chainCerts = new List<X509CertificateEntry>();

    // 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<byte[]>();
    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<Org.BouncyCastle.X509.X509Certificate> BuildCertificateChainBC(byte[] primary,IEnumerable<byte[]> additional)
{
    X509CertificateParser parser = new X509CertificateParser();
    PkixCertPathBuilder builder = new PkixCertPathBuilder();

    // Separate root from itermediate
    var intermediateCerts = new List<Org.BouncyCastle.X509.X509Certificate>();
    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<Org.BouncyCastle.X509.X509Certificate>();
}

private static AsymmetricCipherKeyPair GenerateDsaKeys()
{
    DSACryptoServiceProvider DSA = new DSACryptoServiceProvider();
    var dsaParams = DSA.ExportParameters(true);
    AsymmetricCipherKeyPair keys = DotNetUtilities.GetDsaKeyPair(dsaParams);
    return keys;
}

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

猜你在找的C#相关文章