More .NET components

X.509 certificates

Issuing self-signed (or root CA) certificates #

To issue a self-signed root CA certificate, use CertificateIssuer class:

CSharp

// prepare certificate info
var info = new CertificateInfo();

// specify certificate validity range
info.EffectiveDate = DateTime.Now.AddDays(-1);
info.ExpirationDate = info.EffectiveDate.AddYears(10);

// specify certificate subject (becomes an issuer as well for self-signed certificates)
info.Subject = new DistinguishedName("CN=Custom CA, E=self@example.org");

// specify certificate usage for a CA certificate
info.Usage = KeyUses.DigitalSignature | KeyUses.KeyCertSign | KeyUses.CrlSign;

// sets a unique serial number
info.SetSerialNumber(Guid.NewGuid().ToByteArray());

// use SHA-256 signature algorithm
info.SignatureHashAlgorithm = HashingAlgorithmId.SHA256;

// generate a 2048-bit RSA key for the certificate
PrivateKeyInfo privateKey;
using (var alg = new AsymmetricKeyAlgorithm())
{
    alg.GenerateKey(AsymmetricKeyAlgorithmId.RSA, 2048);
    privateKey = alg.GetPrivateKey();
}

// create the self-signed certificate
Certificate certificate = CertificateIssuer.Issue(info, privateKey);

// associate the private key with the certificate
certificate.Associate(privateKey);

// save the certificate along with its private key to an encrypted PFX/P12 file
// (make sure to keep this in a secure location)
certificate.Save("cacert.pfx", CertificateFormat.Pfx, "password");

// save the certificate (without the private key) to a file
certificate.Save("cacert.cer", CertificateFormat.Base64Der);

The same approach can be used to issue self-signed user certificates - just specify the appropriate usage and e-mail address:

CSharp

// specify certificate subject
info.Subject = new DistinguishedName("CN=Self-signed Certificate, E=someone@example.org");

// set mail address for a client certificate
info.MailAddress = "someone@example.org";

// specify certificate usage for a client or server certificate
info.Usage = KeyUses.DigitalSignature | KeyUses.KeyEncipherment | KeyUses.DataEncipherment;

// specify certificate extended usage for a client certificate
info.SetExtendedUsage(ExtendedUsageOids.ClientAuthentication, ExtendedUsageOids.EmailProtection);

Issuing certificate signed by a custom CA #

It's easily possible to implement a simple custom root certification authority (CA) that can issue and sign certificates:

CSharp

// load the CA certificate (or retrieve it from store)
Certificate ca = Certificate.LoadPfx("cacert.pfx", "password");

// prepare certificate info
var info = new CertificateInfo();

// specify certificate validity range
info.EffectiveDate = DateTime.Now.AddDays(-1);
info.ExpirationDate = info.EffectiveDate.AddYears(1);

// specify certificate subject for a client certificate
info.Subject = new DistinguishedName("CN=Sample Certificate, E=someone@example.org");

// set mail address for a client certificate
info.MailAddress = "someone@example.org";

// specify certificate usage for a client certificate
info.Usage = KeyUses.DigitalSignature | KeyUses.KeyEncipherment | KeyUses.DataEncipherment;

// specify certificate extended usage for a client certificate
info.SetExtendedUsage(ExtendedUsageOids.ClientAuthentication, ExtendedUsageOids.EmailProtection);

// sets a unique serial number
info.SetSerialNumber(Guid.NewGuid().ToByteArray());

// use SHA-256 signature algorithm
info.SignatureHashAlgorithm = HashingAlgorithmId.SHA256;

// add CRL distribution points (optional)
//info.CrlDistributionPoints.Add(new CrlDistributionPoint("http://example.org/crl/TestRootCA.crl"));

// generate a 2048-bit RSA key for the certificate
PrivateKeyInfo privateKey;
using (var alg = new AsymmetricKeyAlgorithm())
{
    alg.GenerateKey(AsymmetricKeyAlgorithmId.RSA, 2048);
    privateKey = alg.GetPrivateKey();
}

// create the certificate signed by the CA certificate
PublicKeyInfo publicKey = privateKey.GetPublicKey();
Certificate certificate = CertificateIssuer.Issue(ca, info, publicKey);

// associate the private key with the certificate
certificate.Associate(privateKey);

// save the certificate along with its private key to an encrypted PFX/P12 file
// (make sure to keep this in a secure location)
certificate.Save("mycert.pfx", CertificateFormat.Pfx, "password");

// save the certificate (without the private key) to a file
certificate.Save("mycert.cer", CertificateFormat.Base64Der);

The same approach can be used to issue server certificates - just specify appropriate usage and host names:

CSharp

// specify certificate subject
info.Subject = new DistinguishedName("CN=example.org, E=someone@example.org");

// specify server hostnames
info.SetAlternativeHostnames("example.org", "www.example.org");

// specify certificate usage for a server certificate
info.Usage = KeyUses.DigitalSignature | KeyUses.KeyEncipherment | KeyUses.DataEncipherment;

// specify certificate extended usage for a server certificate
info.SetExtendedUsage(ExtendedUsageOids.ServerAuthentication);

Issuing CRL for a custom CA #

To issue a certificate revocation list (CRL) for your custom CA, use the following code:

CSharp

// load the CA certificate (or retrieve it from store)
Certificate ca = Certificate.LoadPfx("cacert.pfx", "password");

// get a list of revoked certificates (to be provided by custom code)
IEnumerable<Certificate> revokedCertificates = GetRevokedCertificates();

// specify CRL validity info
var listInfo = new RevocationListInfo();
listInfo.ThisUpdate = DateTime.Now.AddDays(-1);
listInfo.NextUpdate = listInfo.ThisUpdate.AddMonths(1);

// construct revoked certificate info collection
var revokedCollection = new RevokedCertificateCollection();
foreach (var cert in revokedCertificates)
{
    revokedCollection.Add(new RevokedCertificate(cert.GetSerialNumber(), DateTime.Now, RevocationReason.Unspecified));
}

// issue the certificate revocation list (CRL)
CertificateRevocationList crl = CertificateIssuer.IssueRevocationList(ca, SignatureHashAlgorithm.SHA256, listInfo, revokedCollection);

// save the CRL
// (the result should be published to desired location such as "http://yoursite.com/crl/TestRootCA.crl")
File.WriteAllBytes("TestRootCA.crl", crl.ToArray());

Adding certificates to store #

To add a certificate to user's certificate store, use CertificateStore object's Add method:

CSharp

// load a user certificate certificate with associated private key,
// add the certificate to current user's certificate store
// and add the key to current user's key store
Certificate certificate = Certificate.LoadDer("mycert.cer");
using (CertificateStore store = new CertificateStore(CertificateStoreName.My, CertificateStoreLocation.CurrentUser))
{
    store.Add(certificate);
}

// load the public part of a CA certificate
// and add it current user's trusted root certification authority store
// (beware - this will make it trusted by other Windows applications as well)
Certificate ca = Certificate.LoadDer("cacert.cer");
using (CertificateStore store = new CertificateStore(CertificateStoreName.Root, CertificateStoreLocation.CurrentUser))
{
    // this will present a dialog asking for confirmation
    store.Add(ca);
}