https://github.com/lethek/fluentcertificates
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.
https://github.com/lethek/fluentcertificates
ca cert certificate crt fluent fluent-api pem pfx x509
Last synced: 3 months ago
JSON representation
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.
- Host: GitHub
- URL: https://github.com/lethek/fluentcertificates
- Owner: lethek
- License: mit
- Created: 2022-05-06T11:44:40.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2024-07-09T21:16:32.000Z (over 1 year ago)
- Last Synced: 2024-11-12T19:24:10.039Z (11 months ago)
- Topics: ca, cert, certificate, crt, fluent, fluent-api, pem, pfx, x509
- Language: C#
- Homepage:
- Size: 313 KB
- Stars: 6
- Watchers: 2
- Forks: 0
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# 📖 FluentCertificates Overview
⚠️ **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.* ⚠️
[](https://www.nuget.org/packages/FluentCertificates)
[](https://github.com/lethek/FluentCertificates/actions/workflows/dotnet.yml)
[](https://github.com/lethek/FluentCertificates/blob/main/LICENSE)FluentCertificates 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.
## NuGet Packages
This project is published in several NuGet packages:
* [FluentCertificates](https://www.nuget.org/packages/FluentCertificates): Top-level package that imports the Builder, Extensions, and Finder packages.
* [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)
* [FluentCertificates.Extensions](https://www.nuget.org/packages/FluentCertificates.Extensions): Provides additional extension methods. [Examples below](#x509certificate2-extension-methods)
* [FluentCertificates.Finder](https://www.nuget.org/packages/FluentCertificates.Finder): Provides `CertificateFinder` for finding certificates across X509Stores and directories. [Examples below](#certificatefinder-examples)Documentation is incomplete. More examples can be found in the project's [unit tests](https://github.com/lethek/FluentCertificates/tree/main/tests).
## CertificateBuilder Examples
`CertificateBuilder` requires the [FluentCertificates.Builder](https://www.nuget.org/packages/FluentCertificates.Builder) package and is found under the `FluentCertificates` namespace.
### **Minimum Example**
_The absolute minimum needed to create a certificate, whether it's useful or not._
```csharp
using var cert = new CertificateBuilder().Create();
```### **Create a Certificate Signing Request**
_For signing, exporting and passing to a 3rd party CA._
```csharp
//A public & 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
using var keys = RSA.Create();//Creating a CertificateSigningRequest
var csr = new CertificateBuilder()
.SetUsage(CertificateUsage.Server)
.SetSubject(b => b.SetCommonName("*.fake.domain"))
.SetSubjectAlternativeNames(x => x.AddDnsNames("*.fake.domain", "fake.domain"))
.SetKeyPair(keys)
.CreateCertificateSigningRequest();//The CertificateRequest object is accessible here:
var certRequest = csr.CertificateRequest;//CSR can be exported to a string
Console.WriteLine(csr.ToPemString());//Or to a file or StringWriter instance
csr.ExportAsPem("csr.pem");
```### **Build a Self-Signed Web Server Certificate**
_Using the fluent style:_
```csharp
using var webCert = new CertificateBuilder()
.SetFriendlyName("Example self-signed web-server certificate")
.SetUsage(CertificateUsage.Server)
.SetSubject(b => b.SetCommonName("*.fake.domain"))
.SetSubjectAlternativeNames(x => x.AddDnsNames("*.fake.domain", "fake.domain"))
.SetNotAfter(DateTimeOffset.UtcNow.AddMonths(1))
.Create();
```_Or alternatively using object initializers (other examples will use fluent style from now on though):_
```csharp
var builder = new CertificateBuilder() {
FriendlyName = "Example self-signed web-server certificate",
Usage = CertificateUsage.Server,
Subject = new X500NameBuilder().SetCommonName("*.fake.domain"),
SubjectAlternativeNames = new GeneralNameListBuilder().AddDnsNames("*.fake.domain", "fake.domain"),
NotAfter = DateTimeOffset.UtcNow.AddMonths(1)
};
using var webCert = builder.Create();
```### **Build a Certificate Authority (CA)**
```csharp
//A CA's expiry date must be later than that of any certificates it will issue
using var issuer = new CertificateBuilder()
.SetFriendlyName("Example root CA")
.SetUsage(CertificateUsage.CA)
.SetSubject(b => b.SetCommonName("Example root CA"))
.SetNotAfter(DateTimeOffset.UtcNow.AddYears(100))
.Create();
```### **Build a Client-Auth Certificate Signed by a CA**
```csharp
//Note: the 'issuer' certificate used must have a private-key attached in order to sign this new certificate
using var clientAuthCert = new CertificateBuilder()
.SetFriendlyName("Example client-auth certificate")
.SetUsage(CertificateUsage.Client)
.SetSubject(b => b.SetCommonName("User: Michael"))
.SetNotAfter(DateTimeOffset.UtcNow.AddYears(1))
.SetIssuer(issuer)
.Create();
```### **Advanced: Certificate with Customized Extensions**
```csharp
using var customCert = new CertificateBuilder()
.SetFriendlyName("Example certificate with customized extensions")
.SetSubject(b => b.SetCommonName("Example certificate with customized extensions"))
.AddExtension(new X509BasicConstraintsExtension(false, false, 0, true))
.AddExtension(new X509KeyUsageExtension(X509KeyUsageFlags.DigitalSignature | X509KeyUsageFlags.KeyEncipherment | X509KeyUsageFlags.DataEncipherment, true))
.AddExtension(new X509EnhancedKeyUsageExtension(new OidCollection { new Oid(Oids.AnyExtendedKeyUsage) }, false))
.SetIssuer(issuer)
.Create();
```### **Advanced: Certificates with Custom Name Constraints and CRL Distribution Points**
```csharp
//Permit the CA cert to issue certificates for specific names and IP addresses
var permittedNames = new GeneralNameListBuilder()
.AddDnsName(".mydomain.local")
.AddEmailAddress("@mydomain.local")
.AddIPAddress(ipAddress: "192.168.0.0", subnetMask: "255.255.255.0")
.Create();using var issuer = new CertificateBuilder()
.SetFriendlyName("Example constrained root CA")
.SetUsage(CertificateUsage.CA)
.SetSubject(b => b.SetCommonName("Example constrained root CA"))
.SetNotAfter(DateTimeOffset.UtcNow.AddMonths(1))
.SetPathLength(1)
.AddExtension(new X509NameConstraintExtension(permittedNames, null))
.Create();using var webCert = new CertificateBuilder()
.SetFriendlyName("Example certificate with a CRL distribution point")
.SetUsage(CertificateUsage.Server)
.SetIssuer(issuer)
.SetSubject(b => b.SetCommonName("*.mydomain.local"))
.SetSubjectAlternativeNames(x => x.AddDnsName("*.mydomain.local"))
//Extension specifies CRL URLs
.AddExtension(CertificateRevocationListBuilder.BuildCrlDistributionPointExtension([$"http://crl.mydomain.local/"]))
.Create();
```---
## CertificateFinder Examples
`CertificateFinder` requires the [FluentCertificates.Finder](https://www.nuget.org/packages/FluentCertificates.Finder) package and is found under the `FluentCertificates` namespace.
The 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.
### **Find a Specific Certificate by Thumbprint**
_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._
```csharp
const string thumbprint = "622A2B8374D9BBE3969B91EDBC8F5152783AFC78";var cert = new CertificateFinder()
.AddCommonStores()
.FirstOrDefault(x => x.Certificate.Thumbprint.Equals(thumbprint, StringComparison.OrdinalIgnoreCase));
```### **Find a Valid Certificate with Matching Subject, Giving Preference to Included Private Keys**
```csharp
var subject = new X500NameBuilder()
.SetOrganization("My Org")
.SetCountry("AU")
.SetCommonName("fake.domain");var cert = new CertificateFinder()
.AddCommonStores()
.Select(x => x.Certificate)
.Where(x => x.IsValidNow())
.OrderBy(x => !x.HasPrivateKey) //Ensure certs with private keys are listed before those without
.FirstOrDefault(x => subject.EquivalentTo(x.SubjectName, false));
```---
## X500NameBuilder Examples
`X500NameBuilder` requires the [FluentCertificates.Builder](https://www.nuget.org/packages/FluentCertificates.Builder) package and is found under the `FluentCertificates` namespace.
*TODO: document this; see unit tests for more examples*
---
## X509Certificate2 Extension Methods
These extension methods require the [FluentCertificates.Builder](https://www.nuget.org/packages/FluentCertificates.Builder) package and are found under the `FluentCertificates` namespace.
*TODO: document these; see unit tests for more examples*
|Extension-Method|Description|
|-|-|
|`BuildChain`||
|`ExportAsCert`||
|`ExportAsPkcs12`||
|`ExportAsPkcs7`||
|`ExportAsPem`||
|`ToPemString`||
|`ToBase64String`||
|`GetPrivateKey`||
|`GetSignatureData`||
|`GetToBeSignedData`||
|`IsValidNow`||
|`IsValidAt`||
|`IsSelfSigned`||
|`IsIssuedBy`||
|`VerifyChain`||---
## X509Chain Extension Methods
These extension methods require the [FluentCertificates.Builder](https://www.nuget.org/packages/FluentCertificates.Builder) package and are found under the `FluentCertificates` namespace.
*TODO: document these*
|Extension-Method|Description|
|-|-|
|`ToCollection`||
|`ToEnumerable`||
|`ExportAsPkcs7`||
|`ExportAsPkcs12`||
|`ExportAsPem`||
|`ToPemString`||---
## X509Certificate2Collection Extension Methods
These extension methods require the [FluentCertificates.Builder](https://www.nuget.org/packages/FluentCertificates.Builder) package and are found under the `FluentCertificates` namespace.
*TODO: document these*
|Extension-Method|Description|
|-|-|
|`ToEnumerable`||
|`ExportAsPkcs7`||
|`ExportAsPkcs12`||
|`ExportAsPem`||
|`ToPemString`||---
## IEnumerable Extension Methods
These extension methods require the [FluentCertificates.Builder](https://www.nuget.org/packages/FluentCertificates.Builder) package and are found under the `FluentCertificates` namespace.
*TODO: document these*
|Extension-Method|Description|
|-|-|
|`ToCollection`||
|`FilterPrivateKeys`||
|`ExportAsPkcs7`||
|`ExportAsPkcs12`||
|`ExportAsPem`||
|`ToPemString`||---
## AsymmetricAlgorithm Extension Methods
These extension methods require the [FluentCertificates.Builder](https://www.nuget.org/packages/FluentCertificates.Builder) package and are found under the `FluentCertificates` namespace.
*TODO: document these*
|Extension-Method|Description|
|-|-|
|`ToPrivateKeyPemString`||
|`ToPublicKeyPemString`||
|`ExportAsPrivateKeyPem`||
|`ExportAsPublicKeyPem`||---
## CertificateRequest Extension Methods
These extension methods require the [FluentCertificates.Builder](https://www.nuget.org/packages/FluentCertificates.Builder) package and are found under the `FluentCertificates` namespace.
|Extension-Method|Description|
|-|-|
|`ToPemString()`|Exports the `CertificateRequest` to a PEM string.|
|`ExportAsPem(string path)`|Exports the `CertificateRequest` to the specified PEM file.|
|`ExportAsPem(TextWriter writer)`|Exports the `CertificateRequest` in PEM format to the given `TextWriter`.|
|`ConvertToBouncyCastle()`|Converts the `CertificateRequest` to a BouncyCastle `Pkcs10CertificationRequest`|---
## X509Extension Extension Methods
These extension methods require the [FluentCertificates.Builder](https://www.nuget.org/packages/FluentCertificates.Builder) package and are found under the `FluentCertificates` namespace.
|Extension-Method|Description|
|-|-|
|`dnExtension.ConvertToBouncyCastle()`|Converts a DotNet `X509Extension` to a BouncyCastle `X509Extension`.|
|`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.|
|`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.|