如何使用BouncyCastle的生成是由根证书签名的根证书,然后站点证书? [英] How do I use BouncyCastle to generate a Root Certificate and then a site certificate that is signed by that Root certificate?

查看:2121
本文介绍了如何使用BouncyCastle的生成是由根证书签名的根证书,然后站点证书?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to build a self hosted service that uses WebAPI with SSL and I need to be able to self-generate SSL certificates to use. I want to be able to do this all from C#. I've been playing with BouncyCastle.

我需要生成两证,根部和站点证书。然后,我需要在Windows在正确的位置安装它们。

I need to generate 2 certificates, a root and a site certificate. Then I need to install them in Windows in their correct places.

我无法弄清楚如何使我的第二个证书引用我的根CA我用尽了一切只是让我不受信任的证书错误。任何帮助,将不胜感激。

I can't figure out how to make my second certificate reference my root ca. Everything I've tried just gets me an untrusted certificate error. Any help would be appreciated.

推荐答案

这是我做什么(我使用DSA,但如果您使用的是RSA,只是改变了密钥生成)。

This is what I do (I'm using DSA, but if you are using RSA, just change the key generation).

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<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, string password,
    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();
    }
}



缺少一些方法:

Some missing methods:

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存储在客户机,以及客户端证书(也可能是在个人或第三方存储)。

Also: you have to install you CA certificate into the Trusted CAs store in the client machine, as well as the client certificate (it could be in the Personal or ThirdParty store).

这篇关于如何使用BouncyCastle的生成是由根证书签名的根证书,然后站点证书?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆