The project is a fork of https://github.com/fszlin/certes with packaging updates, feature updates and experimental extensions.
This library is an ACME client implementation primarily used by https://certifytheweb.com and is subject to changes required by that application.
Extended Features:
- ACME ARI (renewal info)
- Certificate chain build does not require installed/embedded root cert
- Optional use of modern PFX cert/key algorithms for OpenSSL 3.x+ compatibility
- Authority token challenges, tkauth-01 and TnAuthList
Creating new ACME account:
var acme = new AcmeContext(WellKnownServers.LetsEncryptStagingV2);
var account = await acme.NewAccount("admin@example.com", true);
// Save the account key for later use
var pemKey = acme.AccountKey.ToPem();
Use an existing ACME account:
// Load the saved account key
var accountKey = KeyFactory.FromPem(pemKey);
var acme = new AcmeContext(WellKnownServers.LetsEncryptStagingV2, accountKey);
var account = await acme.Account();
See API doc for additional operations.
Place a wildcard certificate order (DNS validation is required for wildcard certificates)
var order = await acme.NewOrder(new[] { "*.your.domain.name" });
Generate the value for DNS TXT record
var authz = (await order.Authorizations()).First();
var dnsChallenge = await authz.Dns();
var dnsTxt = acme.AccountKey.DnsTxt(dnsChallenge.Token);
Add a DNS TXT record to _acme-challenge.your.domain.name
with dnsTxt
value.
For non-wildcard certificate, HTTP challenge is also available
var order = await acme.NewOrder(new[] { "your.domain.name" });
Get the token and key authorization string
var authz = (await order.Authorizations()).First();
var httpChallenge = await authz.Http();
var keyAuthz = httpChallenge.KeyAuthz;
Save the key authorization string in a text file,
and upload it to http://your.domain.name/.well-known/acme-challenge/<token>
Ask the ACME server to validate our domain ownership
await challenge.Validate();
Download the certificate once validation is done
var privateKey = KeyFactory.NewKey(KeyAlgorithm.ES256);
var cert = await order.Generate(new CsrInfo
{
CommonName = "your.domain.name",
}, privateKey);
Export full chain certification
var certPem = cert.ToPem();
Export PFX
var pfxBuilder = cert.ToPfx(privateKey);
var pfx = pfxBuilder.Build("my-cert", "abcd1234");