即时生成自签名证书

Posted

技术标签:

【中文标题】即时生成自签名证书【英文标题】:Generate a self-signed certificate on the fly 【发布时间】:2014-04-09 11:00:07 【问题描述】:

我四处寻找,但没有找到一个明确的例子。 我想以编程方式 (C#) 创建一个自签名(自)受信任的证书,请执行以下步骤:

第 1 步:

即时创建根 CA 证书并将其添加到“受信任的根证书颁发机构”文件夹中的证书存储中

我想做这个命令行工具所做的事情:

makecert.exe -sk RootCA -sky signature -pe -n CN=MY_CA -r -sr LocalMachine -ss Root MyCA.cer

第 2 步:

根据之前创建的根 CA 证书创建一个证书,并将其放入证书存储中的“个人”文件夹中

我想做这个命令行工具所做的事情:

makecert.exe -sk server -sky exchange -pe -n CN=127.0.0.1 -ir LocalMachine -is Root -ic MyCA.cer -sr LocalMachine -ss My MyCertificate.cer

我想得到这个:

我做到了(请参阅以下代码 - 第 1 步)。如何进行第 2 步?目标机器是 Windows XP/7。

我尝试了纯 .NET 方法和 Bouncy Castle 库

// STEP 1
mycerRoot = generateRootCertV1("MY_CA"); // Tried also generateRootCertV2(BouncyCastle)
addCertToStore(mycerRoot, StoreName.Root, StoreLocation.LocalMachine);

// STEP 2
mycer = generateCert("127.0.0.1", mycerRoot); // ?????? <-- Something like that How to implement generateCert??
addCertToStore(mycer, StoreName.My, StoreLocation.LocalMachine);

public static Org.BouncyCastle.X509.X509Certificate generateRootCertV2(string certName)

    X509V1CertificateGenerator certGen = new X509V1CertificateGenerator();

    X509Name CN = new X509Name("CN=" + certName);

    RsaKeyPairGenerator keypairgen = new RsaKeyPairGenerator();
    keypairgen.Init(new KeyGenerationParameters(new SecureRandom(new CryptoApiRandomGenerator()), 1024));

    AsymmetricCipherKeyPair keypair = keypairgen.GenerateKeyPair();

    certGen.SetSerialNumber(BigInteger.ProbablePrime(120, new Random()));
    certGen.SetIssuerDN(CN);
    certGen.SetNotAfter(DateTime.MaxValue);
    certGen.SetNotBefore(DateTime.Now.Subtract(new TimeSpan(7, 0, 0, 0)));
    certGen.SetSubjectDN(CN);
    certGen.SetPublicKey(keypair.Public);
    certGen.SetSignatureAlgorithm("MD5WithRSA");

    Org.BouncyCastle.X509.X509Certificate newCert = certGen.Generate(keypair.Private);

    return newCert;


public static X509Certificate2 GenerateRootCertV1(string HostNameOrIP_or_CertName)

    X509Certificate2 cert = null;

    try
    
        using (CryptContext ctx = new CryptContext())
        
            ctx.Open();
            cert = ctx.CreateSelfSignedCertificate(
                new SelfSignedCertProperties
                
                    IsPrivateKeyExportable = true,
                    KeyBitLength = 4096,
                    Name = new X500DistinguishedName("cn=" + HostNameOrIP_or_CertName),
                    ValidFrom = DateTime.Today.AddDays(-1),
                    ValidTo = DateTime.Today.AddYears(20),
                );
        
    
    catch (Exception ex)
    
    

    return cert;


public static bool addCertToStore(X509Certificate2 cert, StoreName st, StoreLocation sl)

    bool bRet = false;

    try
    
        X509Store store = new X509Store(st, sl);
        store.Open(OpenFlags.ReadWrite);

        if (cert != null)
        
            byte[] pfx = cert.Export(X509ContentType.Pfx);
            cert = new X509Certificate2(pfx, (string)null, X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.MachineKeySet);

            if (!certExists(store, cert.SubjectName.Name))
            
                store.Add(cert);
                bRet = true;
            
        
        store.Close();
    
    catch
    

    
    return bRet;

【问题讨论】:

也许这会有所帮助:***.com/questions/3736568/… 谢谢,已经访问了那个链接,但是……你能举个例子吗?我不想创建“自签名不受信任的证书”。我想先创建一个根 CA 证书,然后我想根据第一个创建一个证书 看图片(我想得到那个):i57.tinypic.com/2akfayg.png 这里描述了 win/osx 的过程alfilatov.com/posts/how-to-create-self-signed-certificate 【参考方案1】:

我编辑了答案,先做根证书,然后颁发最终实体证书。

以下是通过 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;

并添加到商店(您的代码稍作修改):

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;

及用法:

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

@wakeupneo cmets 之后我还没有编译这个示例代码。 @wakeupneo,您可能需要稍微编辑代码并为每个证书添加适当的扩展。

【讨论】:

【参考方案2】:

好的,感谢您的帮助。这是工作代码:

private void button_Click(object sender, EventArgs e)

    AsymmetricKeyParameter myCAprivateKey = null;

    // Generate a root CA cert and obtain the privateKey
    X509Certificate2 MyRootCAcert = GenerateCACertificate("CN=MYTESTCA", ref myCAprivateKey);

    // Add CA certificate to store
    addCertToStore(MyRootCAcert, StoreName.Root, StoreLocation.LocalMachine);

    // Generate certificate based on the CA certificate privateKey
    X509Certificate2 MyCert = GenerateSelfSignedCertificate("CN=127.0.01", "CN=MYTESTCA", myCAprivateKey);

    // Add certificate to store
    addCertToStore(MyCert, StoreName.My, StoreLocation.LocalMachine);

    MessageBox.Show("Done!");



public static X509Certificate2 GenerateSelfSignedCertificate(string subjectName, string issuerName, AsymmetricKeyParameter issuerPrivKey)

    const int keyStrength = 2048;

    // Generating Random Numbers
    CryptoApiRandomGenerator randomGenerator = new CryptoApiRandomGenerator();
    SecureRandom random = new SecureRandom(randomGenerator);

    // The Certificate Generator
    X509V3CertificateGenerator certificateGenerator = new X509V3CertificateGenerator();

    // Serial Number
    BigInteger 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
    X509Name subjectDN = new X509Name(subjectName);
    X509Name issuerDN = new X509Name(issuerName);
    certificateGenerator.SetIssuerDN(issuerDN);
    certificateGenerator.SetSubjectDN(subjectDN);

    // Valid For
    DateTime notBefore = DateTime.UtcNow.Date;
    DateTime 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
    AsymmetricCipherKeyPair issuerKeyPair = subjectKeyPair;

    // Selfsign certificate
    Org.BouncyCastle.X509.X509Certificate certificate = certificateGenerator.Generate(issuerPrivKey, random);

    // Corresponding private key
    PrivateKeyInfo info = PrivateKeyInfoFactory.CreatePrivateKeyInfo(subjectKeyPair.Private);

    // Merge into X509Certificate2
    X509Certificate2 x509 = new System.Security.Cryptography.X509Certificates.X509Certificate2(certificate.GetEncoded());

    Asn1Sequence seq = (Asn1Sequence)Asn1Object.FromByteArray(info.PrivateKey.GetDerEncoded());
    if (seq.Count != 9)
    
        //throw new PemException("malformed sequence in RSA private key");
    

    RsaPrivateKeyStructure 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 X509Certificate2 GenerateCACertificate(string subjectName, ref AsymmetricKeyParameter CaPrivateKey)

    const int keyStrength = 2048;

    // Generating Random Numbers
    CryptoApiRandomGenerator randomGenerator = new CryptoApiRandomGenerator();
    SecureRandom random = new SecureRandom(randomGenerator);

    // The Certificate Generator
    X509V3CertificateGenerator certificateGenerator = new X509V3CertificateGenerator();

    // Serial Number
    BigInteger 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
    X509Name subjectDN = new X509Name(subjectName);
    X509Name issuerDN = subjectDN;
    certificateGenerator.SetIssuerDN(issuerDN);
    certificateGenerator.SetSubjectDN(subjectDN);

    // Valid For
    DateTime notBefore = DateTime.UtcNow.Date;
    DateTime notAfter = notBefore.AddYears(2);

    certificateGenerator.SetNotBefore(notBefore);
    certificateGenerator.SetNotAfter(notAfter);

    // Subject Public Key
    AsymmetricCipherKeyPair subjectKeyPair;
    KeyGenerationParameters keyGenerationParameters = new KeyGenerationParameters(random, keyStrength);
    RsaKeyPairGenerator keyPairGenerator = new RsaKeyPairGenerator();
    keyPairGenerator.Init(keyGenerationParameters);
    subjectKeyPair = keyPairGenerator.GenerateKeyPair();

    certificateGenerator.SetPublicKey(subjectKeyPair.Public);

    // Generating the Certificate
    AsymmetricCipherKeyPair issuerKeyPair = subjectKeyPair;

    // Selfsign certificate
    Org.BouncyCastle.X509.X509Certificate certificate = certificateGenerator.Generate(issuerKeyPair.Private, random);
    X509Certificate2 x509 = new System.Security.Cryptography.X509Certificates.X509Certificate2(certificate.GetEncoded());

    CaPrivateKey = issuerKeyPair.Private;

    return x509;
    //return issuerKeyPair.Private;


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;

【讨论】:

【参考方案3】:

在整合了多个帖子的更改后,我终于得到了这段代码!

static void Main(string[] args)

    AsymmetricKeyParameter caPrivateKey = null;
    var caCert = GenerateCACertificate("CN=MyROOTCA", ref caPrivateKey);
    addCertToStore(caCert, StoreName.Root, StoreLocation.LocalMachine);

    var clientCert = GenerateSelfSignedCertificate("CN=127.0.0.1", "CN=MyROOTCA", caPrivateKey);

    var p12 = clientCert.Export(X509ContentType.Pfx);

    addCertToStore(new X509Certificate2(p12, (string)null, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet), StoreName.My, StoreLocation.LocalMachine);


public static X509Certificate2 GenerateSelfSignedCertificate(string subjectName, string issuerName, AsymmetricKeyParameter issuerPrivKey)

    const int keyStrength = 2048;

    // Generating Random Numbers
    CryptoApiRandomGenerator randomGenerator = new CryptoApiRandomGenerator();
    SecureRandom random = new SecureRandom(randomGenerator);

    // The Certificate Generator
    X509V3CertificateGenerator certificateGenerator = new X509V3CertificateGenerator();

    // Serial Number
    BigInteger 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
    X509Name subjectDN = new X509Name(subjectName);
    X509Name issuerDN = new X509Name(issuerName);
    certificateGenerator.SetIssuerDN(issuerDN);
    certificateGenerator.SetSubjectDN(subjectDN);

    // Valid For
    DateTime notBefore = DateTime.UtcNow.Date;
    DateTime 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
    AsymmetricCipherKeyPair issuerKeyPair = subjectKeyPair;

    // Selfsign certificate
    Org.BouncyCastle.X509.X509Certificate certificate = certificateGenerator.Generate(issuerPrivKey, random);


    // Corresponding private key
    PrivateKeyInfo info = PrivateKeyInfoFactory.CreatePrivateKeyInfo(subjectKeyPair.Private);


    // Merge into X509Certificate2
    X509Certificate2 x509 = new System.Security.Cryptography.X509Certificates.X509Certificate2(certificate.GetEncoded());

    Asn1Sequence seq = (Asn1Sequence)Asn1Object.FromByteArray(info.PrivateKey.GetDerEncoded());
    if (seq.Count != 9)
    
        //throw new PemException("malformed sequence in RSA private key");
    

    RsaPrivateKeyStructure 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 = ToDotNetKey(rsaparams); //x509.PrivateKey = DotNetUtilities.ToRSA(rsaparams);
    return x509;


public static AsymmetricAlgorithm ToDotNetKey(RsaPrivateCrtKeyParameters privateKey)

    var cspParams = new CspParameters
    
        KeyContainerName = Guid.NewGuid().ToString(),
        KeyNumber = (int)KeyNumber.Exchange,
        Flags = CspProviderFlags.UseMachineKeyStore
    ;

    var rsaProvider = new RSACryptoServiceProvider(cspParams);
    var parameters = new RSAParameters
    
        Modulus = privateKey.Modulus.ToByteArrayUnsigned(),
        P = privateKey.P.ToByteArrayUnsigned(),
        Q = privateKey.Q.ToByteArrayUnsigned(),
        DP = privateKey.DP.ToByteArrayUnsigned(),
        DQ = privateKey.DQ.ToByteArrayUnsigned(),
        InverseQ = privateKey.QInv.ToByteArrayUnsigned(),
        D = privateKey.Exponent.ToByteArrayUnsigned(),
        Exponent = privateKey.PublicExponent.ToByteArrayUnsigned()
    ;

    rsaProvider.ImportParameters(parameters);
    return rsaProvider;


public static X509Certificate2 GenerateCACertificate(string subjectName, ref AsymmetricKeyParameter CaPrivateKey)

    const int keyStrength = 2048;

    // Generating Random Numbers
    CryptoApiRandomGenerator randomGenerator = new CryptoApiRandomGenerator();
    SecureRandom random = new SecureRandom(randomGenerator);

    // The Certificate Generator
    X509V3CertificateGenerator certificateGenerator = new X509V3CertificateGenerator();

    // Serial Number
    BigInteger 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
    X509Name subjectDN = new X509Name(subjectName);
    X509Name issuerDN = subjectDN;
    certificateGenerator.SetIssuerDN(issuerDN);
    certificateGenerator.SetSubjectDN(subjectDN);

    // Valid For
    DateTime notBefore = DateTime.UtcNow.Date;
    DateTime notAfter = notBefore.AddYears(2);

    certificateGenerator.SetNotBefore(notBefore);
    certificateGenerator.SetNotAfter(notAfter);

    // Subject Public Key
    AsymmetricCipherKeyPair subjectKeyPair;
    KeyGenerationParameters keyGenerationParameters = new KeyGenerationParameters(random, keyStrength);
    RsaKeyPairGenerator keyPairGenerator = new RsaKeyPairGenerator();
    keyPairGenerator.Init(keyGenerationParameters);
    subjectKeyPair = keyPairGenerator.GenerateKeyPair();

    certificateGenerator.SetPublicKey(subjectKeyPair.Public);

    // Generating the Certificate
    AsymmetricCipherKeyPair issuerKeyPair = subjectKeyPair;

    // Selfsign certificate
    Org.BouncyCastle.X509.X509Certificate certificate = certificateGenerator.Generate(issuerKeyPair.Private, random);
    X509Certificate2 x509 = new System.Security.Cryptography.X509Certificates.X509Certificate2(certificate.GetEncoded());

    CaPrivateKey = issuerKeyPair.Private;

    return x509;
    //return issuerKeyPair.Private;


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;

【讨论】:

谢谢。我以此为起点创建了 2 个证书。第一个是“受信任的权威”,第二个是由(第一个)签署的。我的对它有一个“微软服务总线”的扭曲。但我能够添加“主题备用名称”和一些 KeyUsages。我在这里发布了我的版本:granadacoder.wordpress.com/2016/11/04/…【参考方案4】:

我们在测试中使用以下代码

(a) NuGet 依赖:Bouncy Castle 1.7.0

<package id="BouncyCastle" version="1.7.0" targetFramework="net40" />

(b) 自签名、中间和 CA 证书的生成器:

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) 示例用法:

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();

【讨论】:

我使用您的代码(非经典)作为对位于 Generate self-signed certificate with root ca signer 的 Powershell 的回答的核心基础。基本上,获胜的答案代码是非冗余的。【参考方案5】:

所以在很长一段时间后我完善了我的答案。 我最初的任务是为 WCF 服务动态创建证书。

我的 Windows 服务应用程序有一个 WCF 服务,如果本地计算机上不存在相关证书,我想在运行时创建通道并创建相关证书。

以上所有代码都是正确的方法,但是缺少一个。

您必须使用嵌入的可导出私钥创建证书。

看到这个link。

这里重点关注sn-p生成私钥的关键部分:

var cspParams = new CspParameters

      KeyContainerName = Guid.NewGuid().ToString(),
      KeyNumber = (int)KeyNumber.Exchange,
      Flags = CspProviderFlags.UseMachineKeyStore
;

如果你在执行netsh命令的时候不这样做,你会得到错误1312。例如,netsh命令的:

netsh http add sslcert ipport=192.168.0.15:8081 certhash=‎5424476237fc2785ed2d0fd620a9131d7c999f6f appid=02639d71-0935-35e8-9d1b-9dd1a2a34627

【讨论】:

以上是关于即时生成自签名证书的主要内容,如果未能解决你的问题,请参考以下文章

自签名证书可以用吗?

如何创建一个自签名的SSL证书

如何创建一个自签名的SSL证书(X509)

如何创建一个自签名的SSL证书

如何创建一个自签名的SSL证书

如何创建一个自签名的SSL证书