There is same question 7 years ago but solved using external library. Now it is possible to change X509Certificate2 Issuer Name
without external library?
public static X509Certificate2 Create(string host)
{
var ecdsa = ECDsa.Create();
var request = new CertificateRequest($"CN={host}", ecdsa, HashAlgorithmName.SHA256);
var validFrom = DateTimeOffset.UtcNow;
var validUntil = DateTimeOffset.UtcNow.AddYears(5);
var certificate = request.CreateSelfSigned(validFrom, validUntil);
var certificateBytes = certificate.Export(X509ContentType.Pfx);
// ??? set issuer ???
return new X509Certificate2(certificateBytes);
}
@bartojs answer is correct I have to use CertificateRequest.Create
.
I'm creating self signing certificate for my MITM Proxy Server application, so here working code for generating certificate in .Net Framework 4.7.2 without external .dll library like Bouncy Castle or CERTENROLLIB
public static X509Certificate2 CreateMyCertificate(string host, bool isCA)
{
var validFrom = DateTimeOffset.UtcNow;
var validUntil = DateTimeOffset.UtcNow.AddYears(8);
X509Certificate2 certificate;
RSA rsaKey = Program.rootRSA;
if (isCA)
{
// create exportable Root private key
// will be used later as global variable Program.rootRSA
CspParameters cspParams = new CspParameters
{
KeyContainerName = Guid.NewGuid().ToString()
};
rsaKey = new RSACryptoServiceProvider(2048, cspParams);
}
// Request a certificate with the common name as the host using the key pair.
// Common Name (AKA CN) represents the server name protected by the SSL certificate.
var request = new CertificateRequest(
$"CN={host}",
rsaKey,
HashAlgorithmName.SHA256,
RSASignaturePadding.Pkcs1
);
// Add Certificate Extensions
request.CertificateExtensions.Add(
new X509EnhancedKeyUsageExtension(
new OidCollection
{
new Oid("1.3.6.1.5.5.7.3.1")
}, true)
);
if (isCA)
{
request.CertificateExtensions.Add(new X509BasicConstraintsExtension(true, true, 1, false));
request.CertificateExtensions.Add(
new X509SubjectKeyIdentifierExtension(request.PublicKey, false));
request.CertificateExtensions.Add(
new X509KeyUsageExtension(X509KeyUsageFlags.CrlSign | X509KeyUsageFlags.KeyCertSign, false));
certificate = request.CreateSelfSigned(validFrom, validUntil);
}
else
{
SubjectAlternativeNameBuilder sanBuilder = new SubjectAlternativeNameBuilder();
sanBuilder.AddDnsName(host.Replace("*.", ""));
request.CertificateExtensions.Add(sanBuilder.Build());
request.CertificateExtensions.Add(new X509Extension("2.5.29.35", Program.authorityKeyIdentifer, false));
request.CertificateExtensions.Add(new X509KeyUsageExtension(
X509KeyUsageFlags.KeyEncipherment, false));
var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
var unixTime = Convert.ToInt64((DateTime.UtcNow - epoch).TotalSeconds);
var serial = BitConverter.GetBytes(unixTime);
certificate = request.Create(Program.rootCert, validFrom, validUntil.AddDays(-5), serial);
certificate.PrivateKey = Program.rootCert.PrivateKey;
}
var certificateBytes = certificate.Export(X509ContentType.Pfx, "");
// return certificate with persisted private key
return new X509Certificate2(certificateBytes, "", X509KeyStorageFlags.Exportable);
}
Then use it like:
rootCert
and rootRSA
rootCert = CreateMyCertificate("__MY_ROOT_CERTIFICATE", true);
rootCert
to trusted Root locationconnect
request we can generate the cert usingCreateMyCertificate("stackoverflow.com", false);
host
certificate make sure rootCert
is defined, because it will be used in CreateMyCertificate()
method, line belowif (isCA){...}
else
{
certificate = request.Create(Program.rootCert, validFrom, validUntil.AddDays(-5), serial);
}
note why you shoud not CERTENROLLIB: