Skip to content

A client implementation for the Automated Certificate Management Environment (ACME) protocol

License

Notifications You must be signed in to change notification settings

webprofusion/anvil

Repository files navigation

Anvil

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

Account

Creating new ACME account:

var acme = new AcmeContext(WellKnownServers.LetsEncryptStagingV2);
var account = await acme.NewAccount("[email protected]", 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.

Order

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" });

Authorization

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>

Validate

Ask the ACME server to validate our domain ownership

await challenge.Validate();

Certificate

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");

About

A client implementation for the Automated Certificate Management Environment (ACME) protocol

Topics

Resources

License

Stars

Watchers

Forks