Last active
October 8, 2024 12:44
-
-
Save svrooij/ec6f664cd93cd09e84414112d23f6a42 to your computer and use it in GitHub Desktop.
C# generate X509Certificate2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* By Stephan van Rooij | |
* See https://svrooij.nl/2018/04/generate-x509certificate2-in-csharp/ | |
*/ | |
using System; | |
using System.Security.Cryptography.X509Certificates; | |
using System.Security.Cryptography; | |
using Org.BouncyCastle.X509; | |
using Org.BouncyCastle.Utilities; | |
using Org.BouncyCastle.Math; | |
using Org.BouncyCastle.Security; | |
using Org.BouncyCastle.Asn1.X509; | |
using Org.BouncyCastle.Crypto; | |
using Org.BouncyCastle.Crypto.Generators; | |
using Org.BouncyCastle.Crypto.Operators; | |
using Org.BouncyCastle.Crypto.Parameters; | |
using Org.BouncyCastle.Pkcs; | |
namespace Selfsigned | |
{ | |
public static class Certificates { | |
public static X509Certificate2 GenerateCertificate(string subject) { | |
var random = new SecureRandom(); | |
var certificateGenerator = new X509V3CertificateGenerator(); | |
var serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random); | |
certificateGenerator.SetSerialNumber(serialNumber); | |
certificateGenerator.SetIssuerDN(new X509Name($"C=NL, O=SomeCompany, CN={subject}")); | |
certificateGenerator.SetSubjectDN(new X509Name($"C=NL, O=SomeCompany, CN={subject}")); | |
certificateGenerator.SetNotBefore(DateTime.UtcNow.Date); | |
certificateGenerator.SetNotAfter(DateTime.UtcNow.Date.AddYears(1)); | |
const int strength = 2048; | |
var keyGenerationParameters = new KeyGenerationParameters(random, strength); | |
var keyPairGenerator = new RsaKeyPairGenerator(); | |
keyPairGenerator.Init(keyGenerationParameters); | |
var subjectKeyPair = keyPairGenerator.GenerateKeyPair(); | |
certificateGenerator.SetPublicKey(subjectKeyPair.Public); | |
var issuerKeyPair = subjectKeyPair; | |
const string signatureAlgorithm = "SHA256WithRSA"; | |
var signatureFactory = new Asn1SignatureFactory(signatureAlgorithm,issuerKeyPair.Private); | |
var bouncyCert = certificateGenerator.Generate(signatureFactory); | |
// Lets convert it to X509Certificate2 | |
X509Certificate2 certificate; | |
Pkcs12Store store = new Pkcs12StoreBuilder().Build(); | |
store.SetKeyEntry($"{subject}_key",new AsymmetricKeyEntry(subjectKeyPair.Private), new [] {new X509CertificateEntry(bouncyCert)}); | |
string exportpw = Guid.NewGuid().ToString("x"); | |
using(var ms = new System.IO.MemoryStream()){ | |
store.Save(ms,exportpw.ToCharArray(),random); | |
certificate = new X509Certificate2(ms.ToArray(),exportpw,X509KeyStorageFlags.Exportable); | |
} | |
//Console.WriteLine($"Generated cert with thumbprint {certificate.Thumbprint}"); | |
return certificate; | |
} | |
// You can also load the certificate from to CurrentUser store | |
private X509Certificate2 LoadCertificate(string subject) { | |
var userStore = new X509Store(StoreName.My,StoreLocation.CurrentUser); | |
userStore.Open(OpenFlags.OpenExistingOnly); | |
if(userStore.IsOpen){ | |
var collection = userStore.Certificates.Find(X509FindType.FindBySubjectName,Environment.MachineName,false); | |
if(collection.Count > 0) { | |
return collection[0]; | |
} | |
userStore.Close(); | |
} | |
return null; | |
} | |
// Or store the certificate to the local store. | |
private void SaveCertificate(X509Certificate2 certificate) { | |
var userStore = new X509Store(StoreName.My,StoreLocation.CurrentUser); | |
userStore.Open(OpenFlags.ReadWrite); | |
userStore.Add(certificate); | |
userStore.Close(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment