Generate a self-signed certificate on the fly

前端 未结 5 892
夕颜
夕颜 2020-11-27 11:27

I searched around, but I didn\'t find a clear example. I want to create a self-signed (self-)trusted certificate programmatically (C#), following these step

5条回答
  •  旧时难觅i
    2020-11-27 11:45

    We are using the following code in our tests

    (a) NuGet dependency: Bouncy Castle 1.7.0

    
    

    (b) Builder for self-signed, intermediate and CA certificates:

    namespace Transport.Tests
    {
        using System;
        using System.Security.Cryptography;
        using System.Security.Cryptography.X509Certificates;
        using Org.BouncyCastle.Asn1;
        using Org.BouncyCastle.Asn1.Pkcs;
        using Org.BouncyCastle.Asn1.X509;
        using Org.BouncyCastle.Crypto;
        using Org.BouncyCastle.Crypto.Generators;
        using Org.BouncyCastle.Crypto.Parameters;
        using Org.BouncyCastle.Crypto.Prng;
        using Org.BouncyCastle.Math;
        using Org.BouncyCastle.OpenSsl;
        using Org.BouncyCastle.Pkcs;
        using Org.BouncyCastle.Security;
        using Org.BouncyCastle.Utilities;
        using Org.BouncyCastle.X509;
        using Org.BouncyCastle.X509.Extension;
    
        public class X509Certificate2Builder
        {
            public string SubjectName
            { set { _subjectName = value; } }
    
            public string IssuerName
            { set { _issuerName = value; } }
    
            public AsymmetricAlgorithm IssuerPrivateKey
            { set { _issuerPrivateKey = value; } }
    
            public X509Certificate2 Issuer
            {
                set
                {
                    _issuer = value;
                    _issuerName = value.IssuerName.Name;
                    if (value.HasPrivateKey)
                        _issuerPrivateKey = value.PrivateKey;
                }
            }
    
            public int? KeyStrength
            { set { _keyStrength = value ?? 2048; } }
    
            public DateTime? NotBefore
            { set { _notBefore = value; } }
    
            public DateTime? NotAfter
            { set { _notAfter = value; } }
    
            public bool Intermediate
            { set { _intermediate = value; } }
    
            private string _subjectName;
            private X509Certificate2 _issuer;
            private string _issuerName;
            private AsymmetricAlgorithm _issuerPrivateKey;
            private int _keyStrength = 2048;
            private DateTime? _notBefore;
            private DateTime? _notAfter;
            private bool _intermediate = true;
    
            public X509Certificate2 Build()
            {
                // Generating Random Numbers
                var randomGenerator = new CryptoApiRandomGenerator();
                var random = new SecureRandom(randomGenerator);
    
                // The Certificate Generator
                var certificateGenerator = new X509V3CertificateGenerator();
    
                // Serial Number
                var serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(long.MaxValue), random);
                certificateGenerator.SetSerialNumber(serialNumber);
    
                // Signature Algorithm
                certificateGenerator.SetSignatureAlgorithm("SHA256WithRSA");
    
                // Issuer and Subject Name
                certificateGenerator.SetIssuerDN(new X509Name(_issuerName ?? _subjectName));
                certificateGenerator.SetSubjectDN(new X509Name(_subjectName));
    
                // Authority Key Identifier
                if (_issuer != null)
                {
                    var authorityKeyIdentifier = new AuthorityKeyIdentifierStructure(
                        DotNetUtilities.FromX509Certificate(_issuer));
                    certificateGenerator.AddExtension(
                        X509Extensions.AuthorityKeyIdentifier.Id, false, authorityKeyIdentifier);
                }
    
                // Basic Constraints - certificate is allowed to be used as intermediate.
                certificateGenerator.AddExtension(
                    X509Extensions.BasicConstraints.Id, true, new BasicConstraints(_intermediate));
    
                // Valid For
                certificateGenerator.SetNotBefore(_notBefore ?? DateTime.UtcNow.Date);
                certificateGenerator.SetNotAfter(_notAfter ?? DateTime.UtcNow.Date.AddYears(2));
    
                // Subject Public Key
                var keyGenerationParameters = new KeyGenerationParameters(random, _keyStrength);
                var keyPairGenerator = new RsaKeyPairGenerator();
                keyPairGenerator.Init(keyGenerationParameters);
    
                var subjectKeyPair = keyPairGenerator.GenerateKeyPair();
                var issuerKeyPair = _issuerPrivateKey == null
                    ? subjectKeyPair
                    : DotNetUtilities.GetKeyPair(_issuerPrivateKey);
    
                certificateGenerator.SetPublicKey(subjectKeyPair.Public);
    
                // selfsign certificate
                var certificate = certificateGenerator.Generate(issuerKeyPair.Private, random);
    
                // Merge into X509Certificate2
                return new X509Certificate2(certificate.GetEncoded())
                {
                    PrivateKey = ConvertToRsaPrivateKey(subjectKeyPair)
                };
            }
    
            private static AsymmetricAlgorithm ConvertToRsaPrivateKey(AsymmetricCipherKeyPair keyPair)
            {
                var keyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(keyPair.Private);
                var seq = (Asn1Sequence) Asn1Object.FromByteArray(keyInfo.PrivateKey.GetDerEncoded());
                if (seq.Count != 9)
                    throw new PemException("malformed sequence in RSA private key");
    
                var rsa = new RsaPrivateKeyStructure(seq);
                var rsaparams = new RsaPrivateCrtKeyParameters(
                    rsa.Modulus, rsa.PublicExponent, rsa.PrivateExponent, rsa.Prime1, rsa.Prime2, rsa.Exponent1,
                    rsa.Exponent2, rsa.Coefficient);
    
                return DotNetUtilities.ToRSA(rsaparams);
            }
        }
    }
    

    (c) Example usage:

    var ca1 = new X509Certificate2Builder {SubjectName = "CN=Test CA1"}.Build();
    var in1A = new X509Certificate2Builder { SubjectName = "CN=Intermediate 1A", Issuer = ca1}.Build();
    var in1B = new X509Certificate2Builder { SubjectName = "CN=Intermediate 1B", Issuer = in1A}.Build();
    var cert1 = new X509Certificate2Builder { SubjectName = "CN=Test 1", Issuer = in1B, Intermediate = false }.Build();
    var cert1B = new X509Certificate2Builder { SubjectName = "CN=Test 1B", Issuer = cert1}.Build();
    
    var ca2 = new X509Certificate2Builder { SubjectName = "CN=Test CA2"}.Build();
    var cert2 = new X509Certificate2Builder { SubjectName = "CN=Test 2", Issuer = ca2, Intermediate = false}.Build();
    
    var invalidCert1 = new X509Certificate2Builder
    {
        SubjectName = "CN=Invalid 1",
        IssuerName = ca1.SubjectName.Name,
        IssuerPrivateKey = ca2.PrivateKey
    }.Build();
    var invalidCert2 = new X509Certificate2Builder
    {
        SubjectName = "CN=Invalid 2",
        Issuer = ca2,
        NotBefore = DateTime.Now.AddDays(1)
    }.Build();
    

提交回复
热议问题