{"id":21317971,"url":"https://github.com/lethek/fluentcertificates","last_synced_at":"2025-07-12T02:33:00.281Z","repository":{"id":38303546,"uuid":"489332958","full_name":"lethek/FluentCertificates","owner":"lethek","description":"FluentCertificates is a library using the Immutable Fluent Builder pattern for easily creating, finding and exporting certificates. Makes it simple to generate your own certificate chains, or just stand-alone self-signed certificates.","archived":false,"fork":false,"pushed_at":"2024-07-09T21:16:32.000Z","size":321,"stargazers_count":6,"open_issues_count":3,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-11-12T19:24:10.039Z","etag":null,"topics":["ca","cert","certificate","crt","fluent","fluent-api","pem","pfx","x509"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lethek.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2022-05-06T11:44:40.000Z","updated_at":"2024-10-15T10:22:36.000Z","dependencies_parsed_at":"2023-01-22T09:00:58.750Z","dependency_job_id":null,"html_url":"https://github.com/lethek/FluentCertificates","commit_stats":{"total_commits":153,"total_committers":2,"mean_commits":76.5,"dds":"0.013071895424836555","last_synced_commit":"4abe876c98818eccdec91440b673edb54c1bdacd"},"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lethek%2FFluentCertificates","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lethek%2FFluentCertificates/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lethek%2FFluentCertificates/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lethek%2FFluentCertificates/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lethek","download_url":"https://codeload.github.com/lethek/FluentCertificates/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225787457,"owners_count":17524108,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ca","cert","certificate","crt","fluent","fluent-api","pem","pfx","x509"],"created_at":"2024-11-21T19:10:23.045Z","updated_at":"2025-07-12T02:33:00.257Z","avatar_url":"https://github.com/lethek.png","language":"C#","readme":"# 📖 FluentCertificates Overview\n\n⚠️ **Note:** *while version numbers are v0.x.y, this software is under initial development and there there may be breaking-changes in its API between minor versions.* ⚠️\n\n[![NuGet](https://img.shields.io/nuget/v/FluentCertificates.svg)](https://www.nuget.org/packages/FluentCertificates)\n[![Build \u0026 Publish](https://github.com/lethek/FluentCertificates/actions/workflows/dotnet.yml/badge.svg)](https://github.com/lethek/FluentCertificates/actions/workflows/dotnet.yml)\n[![GitHub license](https://img.shields.io/github/license/lethek/FluentCertificates)](https://github.com/lethek/FluentCertificates/blob/main/LICENSE)\n\nFluentCertificates is a library using the Immutable Fluent Builder pattern for easily creating, finding, and exporting certificates. It makes it simple to generate your own certificate chains or just stand-alone self-signed certificates.\n\n## NuGet Packages\n\nThis project is published in several NuGet packages:\n\n* [FluentCertificates](https://www.nuget.org/packages/FluentCertificates): Top-level package that imports the Builder, Extensions, and Finder packages.\n* [FluentCertificates.Builder](https://www.nuget.org/packages/FluentCertificates.Builder): Provides `CertificateBuilder` for building certificates and also includes a bunch of convenient extension methods. [Examples below](#certificatebuilder-examples)\n* [FluentCertificates.Extensions](https://www.nuget.org/packages/FluentCertificates.Extensions): Provides additional extension methods. [Examples below](#x509certificate2-extension-methods)\n* [FluentCertificates.Finder](https://www.nuget.org/packages/FluentCertificates.Finder): Provides `CertificateFinder` for finding certificates across X509Stores and directories. [Examples below](#certificatefinder-examples)\n\nDocumentation is incomplete. More examples can be found in the project's [unit tests](https://github.com/lethek/FluentCertificates/tree/main/tests).\n\n## CertificateBuilder Examples\n\n`CertificateBuilder` requires the [FluentCertificates.Builder](https://www.nuget.org/packages/FluentCertificates.Builder) package and is found under the `FluentCertificates` namespace.\n\n### **Minimum Example**\n\n_The absolute minimum needed to create a certificate, whether it's useful or not._\n\n```csharp\nusing var cert = new CertificateBuilder().Create();\n```\n\n### **Create a Certificate Signing Request**\n\n_For signing, exporting and passing to a 3rd party CA._\n\n```csharp\n//A public \u0026 private keypair must be created first, outside of the CertificateBuilder, otherwise you'd have no way to retrieve the private-key used for the new CertificateSigningRequest object\nusing var keys = RSA.Create();\n\n//Creating a CertificateSigningRequest\nvar csr = new CertificateBuilder()\n    .SetUsage(CertificateUsage.Server)\n    .SetSubject(b =\u003e b.SetCommonName(\"*.fake.domain\"))\n    .SetSubjectAlternativeNames(x =\u003e x.AddDnsNames(\"*.fake.domain\", \"fake.domain\"))\n    .SetKeyPair(keys)\n    .CreateCertificateSigningRequest();\n\n//The CertificateRequest object is accessible here:\nvar certRequest = csr.CertificateRequest;\n\n//CSR can be exported to a string\nConsole.WriteLine(csr.ToPemString());\n\n//Or to a file or StringWriter instance\ncsr.ExportAsPem(\"csr.pem\");\n```\n\n### **Build a Self-Signed Web Server Certificate**\n\n_Using the fluent style:_\n\n```csharp\nusing var webCert = new CertificateBuilder()\n    .SetFriendlyName(\"Example self-signed web-server certificate\")\n    .SetUsage(CertificateUsage.Server)\n    .SetSubject(b =\u003e b.SetCommonName(\"*.fake.domain\"))\n    .SetSubjectAlternativeNames(x =\u003e x.AddDnsNames(\"*.fake.domain\", \"fake.domain\"))\n    .SetNotAfter(DateTimeOffset.UtcNow.AddMonths(1))\n    .Create();\n```\n\n_Or alternatively using object initializers (other examples will use fluent style from now on though):_\n```csharp\nvar builder = new CertificateBuilder() {\n    FriendlyName = \"Example self-signed web-server certificate\",\n    Usage = CertificateUsage.Server,\n    Subject = new X500NameBuilder().SetCommonName(\"*.fake.domain\"),\n    SubjectAlternativeNames = new GeneralNameListBuilder().AddDnsNames(\"*.fake.domain\", \"fake.domain\"),\n    NotAfter = DateTimeOffset.UtcNow.AddMonths(1)\n};\nusing var webCert = builder.Create();\n```\n\n### **Build a Certificate Authority (CA)**\n\n```csharp\n//A CA's expiry date must be later than that of any certificates it will issue\nusing var issuer = new CertificateBuilder()\n    .SetFriendlyName(\"Example root CA\")\n    .SetUsage(CertificateUsage.CA)\n    .SetSubject(b =\u003e b.SetCommonName(\"Example root CA\"))\n    .SetNotAfter(DateTimeOffset.UtcNow.AddYears(100))\n    .Create();\n```\n\n### **Build a Client-Auth Certificate Signed by a CA**\n\n```csharp\n//Note: the 'issuer' certificate used must have a private-key attached in order to sign this new certificate\nusing var clientAuthCert = new CertificateBuilder()\n    .SetFriendlyName(\"Example client-auth certificate\")\n    .SetUsage(CertificateUsage.Client)\n    .SetSubject(b =\u003e b.SetCommonName(\"User: Michael\"))\n    .SetNotAfter(DateTimeOffset.UtcNow.AddYears(1))\n    .SetIssuer(issuer)\n    .Create();\n```\n\n### **Advanced: Certificate with Customized Extensions**\n\n```csharp\nusing var customCert = new CertificateBuilder()\n    .SetFriendlyName(\"Example certificate with customized extensions\")\n    .SetSubject(b =\u003e b.SetCommonName(\"Example certificate with customized extensions\"))\n    .AddExtension(new X509BasicConstraintsExtension(false, false, 0, true))\n    .AddExtension(new X509KeyUsageExtension(X509KeyUsageFlags.DigitalSignature | X509KeyUsageFlags.KeyEncipherment | X509KeyUsageFlags.DataEncipherment, true))\n    .AddExtension(new X509EnhancedKeyUsageExtension(new OidCollection { new Oid(Oids.AnyExtendedKeyUsage) }, false))\n    .SetIssuer(issuer)\n    .Create();\n```\n\n### **Advanced: Certificates with Custom Name Constraints and CRL Distribution Points**\n\n```csharp\n//Permit the CA cert to issue certificates for specific names and IP addresses\nvar permittedNames = new GeneralNameListBuilder()\n    .AddDnsName(\".mydomain.local\")\n    .AddEmailAddress(\"@mydomain.local\")\n    .AddIPAddress(ipAddress: \"192.168.0.0\", subnetMask: \"255.255.255.0\")\n    .Create();\n\nusing var issuer = new CertificateBuilder()\n    .SetFriendlyName(\"Example constrained root CA\")\n    .SetUsage(CertificateUsage.CA)\n    .SetSubject(b =\u003e b.SetCommonName(\"Example constrained root CA\"))\n    .SetNotAfter(DateTimeOffset.UtcNow.AddMonths(1))\n    .SetPathLength(1)\n    .AddExtension(new X509NameConstraintExtension(permittedNames, null))\n    .Create();\n\nusing var webCert = new CertificateBuilder()\n    .SetFriendlyName(\"Example certificate with a CRL distribution point\")\n    .SetUsage(CertificateUsage.Server)\n    .SetIssuer(issuer)\n    .SetSubject(b =\u003e b.SetCommonName(\"*.mydomain.local\"))\n    .SetSubjectAlternativeNames(x =\u003e x.AddDnsName(\"*.mydomain.local\"))\n    //Extension specifies CRL URLs\n    .AddExtension(CertificateRevocationListBuilder.BuildCrlDistributionPointExtension([$\"http://crl.mydomain.local/\"]))\n    .Create();\n```\n\n---\n\n## CertificateFinder Examples\n\n`CertificateFinder` requires the [FluentCertificates.Finder](https://www.nuget.org/packages/FluentCertificates.Finder) package and is found under the `FluentCertificates` namespace.\n\nThe CertificateFinder class allows you to configure, add, and query certificate sources (stores and directories) in a fluent and immutable manner. It supports LINQ queries for flexible certificate searching.\n\n### **Find a Specific Certificate by Thumbprint**\n\n_The \"common stores\" include the CurrentUser and LocalMachine certificate stores, such as \"My\", \"Root\", \"CA\", etc. You can also add custom directories or other X509 stores to search for certificates._\n\n```csharp\nconst string thumbprint = \"622A2B8374D9BBE3969B91EDBC8F5152783AFC78\";\n\nvar cert = new CertificateFinder()\n    .AddCommonStores()\n    .FirstOrDefault(x =\u003e x.Certificate.Thumbprint.Equals(thumbprint, StringComparison.OrdinalIgnoreCase));\n```\n\n### **Find a Valid Certificate with Matching Subject, Giving Preference to Included Private Keys**\n\n```csharp\nvar subject = new X500NameBuilder()\n    .SetOrganization(\"My Org\")\n    .SetCountry(\"AU\")\n    .SetCommonName(\"fake.domain\");\n\nvar cert = new CertificateFinder()\n    .AddCommonStores()\n    .Select(x =\u003e x.Certificate)\n    .Where(x =\u003e x.IsValidNow())\n    .OrderBy(x =\u003e !x.HasPrivateKey) //Ensure certs with private keys are listed before those without\n    .FirstOrDefault(x =\u003e subject.EquivalentTo(x.SubjectName, false));\n```\n\n---\n\n## X500NameBuilder Examples\n\n`X500NameBuilder` requires the [FluentCertificates.Builder](https://www.nuget.org/packages/FluentCertificates.Builder) package and is found under the `FluentCertificates` namespace.\n\n*TODO: document this; see unit tests for more examples*\n\n---\n\n## X509Certificate2 Extension Methods\n\nThese extension methods require the [FluentCertificates.Builder](https://www.nuget.org/packages/FluentCertificates.Builder) package and are found under the `FluentCertificates` namespace.\n\n*TODO: document these; see unit tests for more examples*\n\n|Extension-Method|Description|\n|-|-|\n|`BuildChain`||\n|`ExportAsCert`||\n|`ExportAsPkcs12`||\n|`ExportAsPkcs7`||\n|`ExportAsPem`||\n|`ToPemString`||\n|`ToBase64String`||\n|`GetPrivateKey`||\n|`GetSignatureData`||\n|`GetToBeSignedData`||\n|`IsValidNow`||\n|`IsValidAt`||\n|`IsSelfSigned`||\n|`IsIssuedBy`||\n|`VerifyChain`||\n\n---\n\n## X509Chain Extension Methods\n\nThese extension methods require the [FluentCertificates.Builder](https://www.nuget.org/packages/FluentCertificates.Builder) package and are found under the `FluentCertificates` namespace.\n\n*TODO: document these*\n\n|Extension-Method|Description|\n|-|-|\n|`ToCollection`||\n|`ToEnumerable`||\n|`ExportAsPkcs7`||\n|`ExportAsPkcs12`||\n|`ExportAsPem`||\n|`ToPemString`||\n\n---\n\n## X509Certificate2Collection Extension Methods\n\nThese extension methods require the [FluentCertificates.Builder](https://www.nuget.org/packages/FluentCertificates.Builder) package and are found under the `FluentCertificates` namespace.\n\n*TODO: document these*\n\n|Extension-Method|Description|\n|-|-|\n|`ToEnumerable`||\n|`ExportAsPkcs7`||\n|`ExportAsPkcs12`||\n|`ExportAsPem`||\n|`ToPemString`||\n\n---\n\n## IEnumerable\u003cX509Certificate2\u003e Extension Methods\n\nThese extension methods require the [FluentCertificates.Builder](https://www.nuget.org/packages/FluentCertificates.Builder) package and are found under the `FluentCertificates` namespace.\n\n*TODO: document these*\n\n|Extension-Method|Description|\n|-|-|\n|`ToCollection`||\n|`FilterPrivateKeys`||\n|`ExportAsPkcs7`||\n|`ExportAsPkcs12`||\n|`ExportAsPem`||\n|`ToPemString`||\n\n---\n\n## AsymmetricAlgorithm Extension Methods\n\nThese extension methods require the [FluentCertificates.Builder](https://www.nuget.org/packages/FluentCertificates.Builder) package and are found under the `FluentCertificates` namespace.\n\n*TODO: document these*\n\n|Extension-Method|Description|\n|-|-|\n|`ToPrivateKeyPemString`||\n|`ToPublicKeyPemString`||\n|`ExportAsPrivateKeyPem`||\n|`ExportAsPublicKeyPem`||\n\n---\n\n## CertificateRequest Extension Methods\n\nThese extension methods require the [FluentCertificates.Builder](https://www.nuget.org/packages/FluentCertificates.Builder) package and are found under the `FluentCertificates` namespace.\n\n|Extension-Method|Description|\n|-|-|\n|`ToPemString()`|Exports the `CertificateRequest` to a PEM string.|\n|`ExportAsPem(string path)`|Exports the `CertificateRequest` to the specified PEM file.|\n|`ExportAsPem(TextWriter writer)`|Exports the `CertificateRequest` in PEM format to the given `TextWriter`.|\n|`ConvertToBouncyCastle()`|Converts the `CertificateRequest` to a BouncyCastle `Pkcs10CertificationRequest`|\n\n---\n\n## X509Extension Extension Methods\n\nThese extension methods require the [FluentCertificates.Builder](https://www.nuget.org/packages/FluentCertificates.Builder) package and are found under the `FluentCertificates` namespace.\n\n|Extension-Method|Description|\n|-|-|\n|`dnExtension.ConvertToBouncyCastle()`|Converts a DotNet `X509Extension` to a BouncyCastle `X509Extension`.|\n|`bcExtension.ConvertToDotNet(string oid)`|Converts a BouncyCastle `X509Extension` to a DotNet `X509Extension`. A DotNet `X509Extension` includes an OID, but a BouncyCastle one doesn't, therefore one must be supplied in the parameters here.|\n|`bcExtension.ConvertToDotNet(DerObjectIdentifier oid)`|Converts a BouncyCastle `X509Extension` to a DotNet `X509Extension`. A DotNet `X509Extension` includes an OID, but a BouncyCastle one doesn't, therefore one must be supplied in the parameters here.|\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flethek%2Ffluentcertificates","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flethek%2Ffluentcertificates","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flethek%2Ffluentcertificates/lists"}