Skip to content

Instantly share code, notes, and snippets.

@d0nutptr
Created August 8, 2017 04:53
Show Gist options
  • Save d0nutptr/6d8565610a2b3cb3124ac94d7aed7342 to your computer and use it in GitHub Desktop.
Save d0nutptr/6d8565610a2b3cb3124ac94d7aed7342 to your computer and use it in GitHub Desktop.
public class CertificateGenerator {
public X509Certificate CreateCertificate(string domain) {
//read the root ca
X509Certificate rootCert = getRootCA();
//generate our public/private keys for this certificate
RsaKeyPairGenerator keyPairGenerator = new RsaKeyPairGenerator();
keyPairGenerator.Init(new KeyGenerationParameters(new SecureRandom(), 2048));
AsymmetricCipherKeyPair keyPair = keyPairGenerator.GenerateKeyPair();
//create a certificate generator
X509V3CertificateGenerator certificateGenerator = new X509V3CertificateGenerator();
//create our subject and issuer lines for the certificate
X509Name subjectName = new X509Name("CN=" + domain);
X509Name issuerName = rootCA.IssuerDN;
//generate a serial number for the certificate
BigInteger serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), new SecureRandom());
//set certificate validity dates
DateTime notBefore = DateTime.Now;
DateTime notAfter = DateTime.Now.AddDays(1825); //5 years
//these are the signature algorithms we are using for the CSR and certificate
string signatureAlgorithm = "SHA256WithRSAEncryption";
string requestSignatureAlgorithm = "SHA256withRSA";
//create certificate signing request
Pkcs10CertificationRequest certificationRequest = new Pkcs10CertificationRequest(requestSignatureAlgorithm, subjectName, keyPair.Public, null, keyPair.Private);
//set certificate generator parameters
certificateGenerator.SetPublicKey(certificationRequest.GetPublicKey());
certificateGenerator.SetSubjectDN(certificationRequest.GetCertificationRequestInfo().Subject);
certificateGenerator.SetIssuerDN(issuerName);
certificateGenerator.SetSerialNumber(serialNumber);
certificateGenerator.SetNotBefore(notBefore);
certificateGenerator.SetNotAfter(notAfter);
certificateGenerator.SetSignatureAlgorithm(signatureAlgorithm);
//build certificate chain
certificateGenerator.AddExtension(X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(rootCA));
certificateGenerator.AddExtension(X509Extensions.SubjectKeyIdentifier, false, new SubjectKeyIdentifierStructure(certificationRequest.GetPublicKey()));
//Subject Alternative Name fix (https://bugs.chromium.org/p/chromium/issues/detail?id=308330)
GeneralNames subjectAlternativeName = new GeneralNames(new GeneralName(GeneralName.DnsName, domain));
certificateGenerator.AddExtension(X509Extensions.SubjectAlternativeName, false, subjectAlternativeName);
//IMPORTANT! You need to specify the purposes this certificate can fill
//If you don't specify the purposes, someone could take your certificate and sign _other_ certificates with it.
certificateGenerator.AddExtension(X509Extensions.KeyUsage, true, new KeyUsage(KeyUsage.DigitalSignature
| KeyUsage.KeyEncipherment
| KeyUsage.KeyAgreement
| KeyUsage.NonRepudiation));
certificateGenerator.AddExtension(X509Extensions.BasicConstraints, true, new BasicConstraints(false));
//generate the certificate
return certificateGenerator.Generate(getRootPrivateKey(), secureRandom);
}
private X509Certificate getRootCA()
{
return new X509CertificateParser().ReadCertificate(System.IO.File.ReadAllBytes("root.cer"));
}
private AsymmetricKeyParameter getRootPrivateKey()
{
AsymmetricCipherKeyPair keyPair;
using (var reader = System.IO.File.OpenText("root.key"))
{
keyPair = (AsymmetricCipherKeyPair)new PemReader(reader).ReadObject();
}
return keyPair.Private;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment