This C# sample creates X.509 certificates with the class X509CertificateGenerator: a self-signed certificate, a root (CA) certificate and a user certificate issued by that root. The certificates are saved as PFX (PKCS#12) files protected by a password, with their public part in .cer files.

How to create a certificate in C#

  • Set the validity (ValidFrom, ValidTo), the key (KeySize, or KeyAlgorithm = KeyAlgorithm.ECDSA with an EllipticCurve) and the SignatureAlgorithm.
  • Set the Subject, as a string or attribute by attribute with AddToSubject.
  • Add the key usages and the enhanced key usages with Extensions: digital signature and non-repudiation, document signing, secure e-mail, client authentication.
  • GenerateCertificate(password, isRootCertificate) returns the PFX file as a byte array. To issue the certificate from your own root, load the root first with LoadRootCertificate.

C# code: a self-signed certificate

/// <summary>
/// Creates a self-signed user certificate: the certificate is its own issuer.
/// </summary>
static void CreateSelfSignedCertificate(string pfxFile, string pfxPassword)
{
    X509CertificateGenerator certificateGenerator = new X509CertificateGenerator(LibrarySerialNumber);

    certificateGenerator.ValidFrom = DateTime.Now;
    certificateGenerator.ValidTo = DateTime.Now.AddDays(100);

    certificateGenerator.KeySize = KeySize.KeySize2048Bit;
    certificateGenerator.SignatureAlgorithm = SignatureAlgorithm.SHA256WithRSA;

    certificateGenerator.Subject = "CN=Self signed certificate, OU=Organization Unit, E=selfsigned@email.com";

    certificateGenerator.Extensions.AddKeyUsage(CertificateKeyUsage.DigitalSignature);
    certificateGenerator.Extensions.AddKeyUsage(CertificateKeyUsage.NonRepudiation);

    certificateGenerator.Extensions.AddEnhancedKeyUsage(CertificateEnhancedKeyUsage.DocumentSigning);
    certificateGenerator.Extensions.AddEnhancedKeyUsage(CertificateEnhancedKeyUsage.SecureEmail);

    // No root certificate is loaded: the certificate is signed with its own private key.
    byte[] pfx = certificateGenerator.GenerateCertificate(pfxPassword, false);

    SavePfxAndPublicCertificate(pfxFile, pfxPassword, pfx);

    Console.WriteLine("The self-signed certificate was created.");
}

C# code: a root certificate and a certificate issued by it

/// <summary>
/// Creates a root (CA) certificate, used to issue other certificates.
/// </summary>
static void CreateRootCertificate(string rootPfxFile, string rootPfxPassword)
{
    X509CertificateGenerator certificateGenerator = new X509CertificateGenerator(LibrarySerialNumber);

    // The validity period. On the demo version of the library it is limited to 30 days.
    certificateGenerator.ValidFrom = DateTime.Now;
    certificateGenerator.ValidTo = DateTime.Now.AddYears(10);

    // 4096 bits is the recommended key size for the CA certificates (the key generation takes a few seconds).
    certificateGenerator.KeySize = KeySize.KeySize4096Bit;
    certificateGenerator.SignatureAlgorithm = SignatureAlgorithm.SHA256WithRSA;

    // The subject can be built attribute by attribute...
    certificateGenerator.AddToSubject(SubjectType.CN, "Root certificate, master");
    certificateGenerator.AddToSubject(SubjectType.OU, "Organization Unit Root");
    certificateGenerator.AddToSubject(SubjectType.E, "root@email.com");

    // ...or it can be set as a single string. When it is set, it replaces the attributes added above.
    // certificateGenerator.Subject = "CN=Root certificate master, OU=Organization Unit Root, E=root@email.com";

    // The key usages of a CA certificate: it signs certificates and certificate revocation lists (CRL).
    certificateGenerator.Extensions.AddKeyUsage(CertificateKeyUsage.CertificateSigning);
    certificateGenerator.Extensions.AddKeyUsage(CertificateKeyUsage.CRLSigning);

    // Optionally, a friendly name can be set.
    // certificateGenerator.FriendlyName = "Test Root Certificate";

    // The second parameter (isRootCertificate) is true: a CA certificate is created.
    byte[] rootPfx = certificateGenerator.GenerateCertificate(rootPfxPassword, true);

    SavePfxAndPublicCertificate(rootPfxFile, rootPfxPassword, rootPfx);

    Console.WriteLine("The root certificate was created.");
}

/// <summary>
/// Creates a user certificate issued by the root certificate.
/// </summary>
static void CreateUserCertificate(string rootPfxFile, string rootPfxPassword, string userPfxFile, string userPfxPassword)
{
    X509CertificateGenerator certificateGenerator = new X509CertificateGenerator(LibrarySerialNumber);

    certificateGenerator.ValidFrom = DateTime.Now;
    certificateGenerator.ValidTo = DateTime.Now.AddYears(2);

    // The root certificate (the issuer): the user certificate is signed with its private key.
    certificateGenerator.LoadRootCertificate(File.ReadAllBytes(rootPfxFile), rootPfxPassword);

    certificateGenerator.KeySize = KeySize.KeySize2048Bit;
    certificateGenerator.SignatureAlgorithm = SignatureAlgorithm.SHA256WithRSA;

    certificateGenerator.Subject = "CN=Simple user certificate, OU=Organization Unit User Certificate, E=user@email.com";

    // The key usages of a certificate used to sign documents.
    certificateGenerator.Extensions.AddKeyUsage(CertificateKeyUsage.DigitalSignature);
    certificateGenerator.Extensions.AddKeyUsage(CertificateKeyUsage.NonRepudiation);
    certificateGenerator.Extensions.KeyUsageIsCritical = true;

    // The enhanced key usages (the purposes for which the certificate can be used).
    certificateGenerator.Extensions.AddEnhancedKeyUsage(CertificateEnhancedKeyUsage.DocumentSigning);
    certificateGenerator.Extensions.AddEnhancedKeyUsage(CertificateEnhancedKeyUsage.SecureEmail);
    certificateGenerator.Extensions.AddEnhancedKeyUsage(CertificateEnhancedKeyUsage.ClientAuthentication);

    // Optionally, the location of the revocation information and of the issuer certificate can be added.
    // The validators use them to check if the certificate was revoked:
    // certificateGenerator.Extensions.AddCrlDistributionPoint("http://crl.example.com/root.crl");
    // certificateGenerator.Extensions.AddOcspUrl("http://ocsp.example.com");
    // certificateGenerator.Extensions.AddCaIssuersUrl("http://www.example.com/root.cer");

    // The second parameter (isRootCertificate) is false: an end-entity (user) certificate is created.
    byte[] userPfx = certificateGenerator.GenerateCertificate(userPfxPassword, false);

    SavePfxAndPublicCertificate(userPfxFile, userPfxPassword, userPfx);

    Console.WriteLine("The user certificate was created.");
}

These certificates are meant for testing and for internal use: the other computers trust them only when the root certificate is installed on them. The project also creates an ECDSA certificate (NIST P-256). Without programming, use Certificate Generator.

Run the full sample. The complete Visual Studio project Create PFX Digital Certificates is included in the library download, in the folder NET Sample Projects (.NET 9, .NET 10 and .NET 11) and in NET Framework Sample Projects (.NET Framework 4.6.2), with the test files and a test certificate. Without a serial number the library runs in demo mode. Download the library and the samples · User manual

Frequently asked questions

Can I add a CRL or OCSP address to the certificate?

Yes: Extensions.AddCrlDistributionPoint, AddOcspUrl and AddCaIssuersUrl.

How long can the certificate be valid?

As long as you set in ValidTo. The demo version of the library limits the validity to 30 days.