Generate a self-signed certificate on the fly

前端 未结 5 890
夕颜
夕颜 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条回答
  •  半阙折子戏
    2020-11-27 11:29

    I edited the answer to do the root certificate first and then issue an end entity certificate.

    Here is some example of generating a self-signed certificate through Bouncy Castle:

    public static X509Certificate2 GenerateSelfSignedCertificate(string subjectName, string issuerName, AsymmetricKeyParameter issuerPrivKey,  int keyStrength = 2048)
    {
        // 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(Int64.MaxValue), random);
        certificateGenerator.SetSerialNumber(serialNumber);
    
        // Signature Algorithm
        const string signatureAlgorithm = "SHA256WithRSA";
        certificateGenerator.SetSignatureAlgorithm(signatureAlgorithm);
    
        // Issuer and Subject Name
        var subjectDN = new X509Name(subjectName);
        var issuerDN = new X509Name(issuerName);
        certificateGenerator.SetIssuerDN(issuerDN);
        certificateGenerator.SetSubjectDN(subjectDN);
    
        // Valid For
        var notBefore = DateTime.UtcNow.Date;
        var notAfter = notBefore.AddYears(2);
    
        certificateGenerator.SetNotBefore(notBefore);
        certificateGenerator.SetNotAfter(notAfter);
    
        // Subject Public Key
        AsymmetricCipherKeyPair subjectKeyPair;
        var keyGenerationParameters = new KeyGenerationParameters(random, keyStrength);
        var keyPairGenerator = new RsaKeyPairGenerator();
        keyPairGenerator.Init(keyGenerationParameters);
        subjectKeyPair = keyPairGenerator.GenerateKeyPair();
    
        certificateGenerator.SetPublicKey(subjectKeyPair.Public);
    
        // Generating the Certificate
        var issuerKeyPair = subjectKeyPair;
    
        // Selfsign certificate
        var certificate = certificateGenerator.Generate(issuerPrivKey, random);
    
        // Corresponding private key
        PrivateKeyInfo info = PrivateKeyInfoFactory.CreatePrivateKeyInfo(subjectKeyPair.Private);
    
    
        // Merge into X509Certificate2
        var x509 = new System.Security.Cryptography.X509Certificates.X509Certificate2(certificate.GetEncoded());
    
        var seq = (Asn1Sequence)Asn1Object.FromByteArray(info.PrivateKey.GetDerEncoded());
        if (seq.Count != 9)
            throw new PemException("malformed sequence in RSA private key");
    
        var rsa = new RsaPrivateKeyStructure(seq);
        RsaPrivateCrtKeyParameters rsaparams = new RsaPrivateCrtKeyParameters(
            rsa.Modulus, rsa.PublicExponent, rsa.PrivateExponent, rsa.Prime1, rsa.Prime2, rsa.Exponent1, rsa.Exponent2, rsa.Coefficient);
    
        x509.PrivateKey = DotNetUtilities.ToRSA(rsaparams);
        return x509;
    }
    
    
    public static AsymmetricKeyParameter GenerateCACertificate(string subjectName, int keyStrength = 2048)
    {
        // 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(Int64.MaxValue), random);
        certificateGenerator.SetSerialNumber(serialNumber);
    
        // Signature Algorithm
        const string signatureAlgorithm = "SHA256WithRSA";
        certificateGenerator.SetSignatureAlgorithm(signatureAlgorithm);
    
        // Issuer and Subject Name
        var subjectDN = new X509Name(subjectName);
        var issuerDN = subjectDN;
        certificateGenerator.SetIssuerDN(issuerDN);
        certificateGenerator.SetSubjectDN(subjectDN);
    
        // Valid For
        var notBefore = DateTime.UtcNow.Date;
        var notAfter = notBefore.AddYears(2);
    
        certificateGenerator.SetNotBefore(notBefore);
        certificateGenerator.SetNotAfter(notAfter);
    
        // Subject Public Key
        AsymmetricCipherKeyPair subjectKeyPair;
        var keyGenerationParameters = new KeyGenerationParameters(random, keyStrength);
        var keyPairGenerator = new RsaKeyPairGenerator();
        keyPairGenerator.Init(keyGenerationParameters);
        subjectKeyPair = keyPairGenerator.GenerateKeyPair();
    
        certificateGenerator.SetPublicKey(subjectKeyPair.Public);
    
        // Generating the Certificate
        var issuerKeyPair = subjectKeyPair;
    
        // Selfsign certificate
        var certificate = certificateGenerator.Generate(issuerKeyPair.Private, random);
        var x509 = new System.Security.Cryptography.X509Certificates.X509Certificate2(certificate.GetEncoded());
    
        // Add CA certificate to Root store
        addCertToStore(cert, StoreName.Root, StoreLocation.CurrentUser);
    
        return issuerKeyPair.Private;
    }
    

    And add to the store (your code slightly modified):

    public static bool addCertToStore(System.Security.Cryptography.X509Certificates.X509Certificate2 cert, System.Security.Cryptography.X509Certificates.StoreName st, System.Security.Cryptography.X509Certificates.StoreLocation sl)
    {
        bool bRet = false;
    
        try
        {
            X509Store store = new X509Store(st, sl);
            store.Open(OpenFlags.ReadWrite);
            store.Add(cert);
    
            store.Close();
        }
        catch
        {
    
        }
    
        return bRet;
    }
    

    And usage:

    var caPrivKey = GenerateCACertificate("CN=root ca");
    var cert = GenerateSelfSignedCertificate("CN=127.0.01", "CN=root ca", caPrivKey);
    addCertToStore(cert, StoreName.My, StoreLocation.CurrentUser);
    

    I have not compiled this example code after @wakeupneo comments. @wakeupneo, you might have to slightly edit the code and add proper extensions to each certificate.

提交回复
热议问题