即时生成自签名证书
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
【讨论】:
以上是关于即时生成自签名证书的主要内容,如果未能解决你的问题,请参考以下文章