or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

acme.mdencryption.mdhashing.mdindex.mdnacl.mdopenpgp.mdpublic-key.mdssh.mdutilities.md
tile.json

acme.mddocs/

ACME Certificate Management

The ACME packages provide automated certificate acquisition and management for Let's Encrypt and other ACME-compliant Certificate Authorities. The acme package implements the core ACME protocol, while acme/autocert provides a higher-level API for automatic certificate management.

Package: golang.org/x/crypto/acme

Core ACME protocol implementation for certificate lifecycle management.

Constants

const (
    LetsEncryptURL = "https://acme-v02.api.letsencrypt.org/directory"
    ALPNProto      = "acme-tls/1"
)

const (
    StatusDeactivated = "deactivated"
    StatusExpired     = "expired"
    StatusInvalid     = "invalid"
    StatusPending     = "pending"
    StatusProcessing  = "processing"
    StatusReady       = "ready"
    StatusRevoked     = "revoked"
    StatusUnknown     = "unknown"
    StatusValid       = "valid"
)

Variables

var (
    ErrUnsupportedKey       = errors.New("acme: unknown key type; only RSA and ECDSA are supported")
    ErrAccountAlreadyExists = errors.New("acme: account already exists")
    ErrNoAccount            = errors.New("acme: account does not exist")
)

Client Operations

type Client struct {
    // Key is the account private key used to register with and
    // authenticate to the CA.
    Key crypto.Signer

    // HTTPClient optionally specifies an HTTP client to use
    // instead of http.DefaultClient.
    HTTPClient *http.Client

    // DirectoryURL is the ACME directory URL.
    DirectoryURL string

    // RetryBackoff computes the duration after which the nth retry of a failed request
    // should occur. If nil, the default exponential backoff is used.
    RetryBackoff func(n int, r *http.Request, resp *http.Response) time.Duration

    // UserAgent is prepended to the User-Agent header sent to the ACME server.
    UserAgent string

    // KID is the key identity for the account.
    KID KeyID
}

// Discover performs ACME server discovery using c.DirectoryURL.
func (c *Client) Discover(ctx context.Context) (Directory, error)

// Register creates a new account with the ACME CA.
// It returns the registered account. The account acct is not modified.
func (c *Client) Register(ctx context.Context, acct *Account, prompt func(tosURL string) bool) (*Account, error)

// GetReg retrieves an existing account associated with c.Key.
func (c *Client) GetReg(ctx context.Context, url string) (*Account, error)

// UpdateReg updates an existing account.
// It returns an updated account copy. The provided account is not modified.
func (c *Client) UpdateReg(ctx context.Context, acct *Account) (*Account, error)

// DeactivateReg permanently deactivates the account associated with the given URL.
func (c *Client) DeactivateReg(ctx context.Context) error

// AccountKeyRollover replaces the account's current key with newKey.
func (c *Client) AccountKeyRollover(ctx context.Context, newKey crypto.Signer) error

// Authorize performs the initial step in the pre-authorization flow.
// Deprecated: Use AuthorizeOrder instead.
func (c *Client) Authorize(ctx context.Context, domain string) (*Authorization, error)

// AuthorizeIP is the same as Authorize but for IP addresses.
// Deprecated: Use AuthorizeOrder instead.
func (c *Client) AuthorizeIP(ctx context.Context, ipaddr string) (*Authorization, error)

// AuthorizeOrder creates a new order authorization for the given identifiers.
func (c *Client) AuthorizeOrder(ctx context.Context, id []AuthzID, opt ...OrderOption) (*Order, error)

// GetAuthorization retrieves an authorization specified by the given URL.
func (c *Client) GetAuthorization(ctx context.Context, url string) (*Authorization, error)

// WaitAuthorization polls an authorization at the given URL until it is in one of the final states.
func (c *Client) WaitAuthorization(ctx context.Context, url string) (*Authorization, error)

// RevokeAuthorization relinquishes a completed authorization.
func (c *Client) RevokeAuthorization(ctx context.Context, url string) error

// GetChallenge retrieves the current status of a challenge.
func (c *Client) GetChallenge(ctx context.Context, url string) (*Challenge, error)

// Accept informs the server that the client accepts one of its challenges.
func (c *Client) Accept(ctx context.Context, chal *Challenge) (*Challenge, error)

// HTTP01ChallengePath returns the URL path for the HTTP-01 challenge response.
func (c *Client) HTTP01ChallengePath(token string) string

// HTTP01ChallengeResponse returns the response body for the HTTP-01 challenge.
func (c *Client) HTTP01ChallengeResponse(token string) (string, error)

// DNS01ChallengeRecord returns the DNS record value for the DNS-01 challenge.
func (c *Client) DNS01ChallengeRecord(token string) (string, error)

// TLSALPN01ChallengeCert creates a certificate for the TLS-ALPN-01 challenge.
func (c *Client) TLSALPN01ChallengeCert(token, identifier string, opt ...CertOption) (cert tls.Certificate, err error)

// GetOrder retrieves an order identified by the given URL.
func (c *Client) GetOrder(ctx context.Context, url string) (*Order, error)

// WaitOrder polls the order at the given URL until it is in one of the final states.
func (c *Client) WaitOrder(ctx context.Context, url string) (*Order, error)

// CreateOrderCert submits the CSR (Certificate Signing Request) to finalize the order
// and fetches the issued certificate chain.
func (c *Client) CreateOrderCert(ctx context.Context, url string, csr []byte, bundle bool) (der [][]byte, certURL string, err error)

// FetchCert retrieves already issued certificate from the given URL, in DER format.
func (c *Client) FetchCert(ctx context.Context, url string, bundle bool) ([][]byte, error)

// ListCertAlternates returns alternate certificate chain URLs for the certificate.
func (c *Client) ListCertAlternates(ctx context.Context, url string) ([]string, error)

// RevokeCert revokes a previously issued certificate.
func (c *Client) RevokeCert(ctx context.Context, key crypto.Signer, cert []byte, reason CRLReasonCode) error

// CreateCert is the legacy method for creating certificates.
// Deprecated: Use AuthorizeOrder and CreateOrderCert instead.
func (c *Client) CreateCert(ctx context.Context, csr []byte, exp time.Duration, bundle bool) (der [][]byte, certURL string, err error)

// TLSSNI01ChallengeCert creates a certificate for the TLS-SNI-01 challenge.
// Deprecated: The TLS-SNI-01 challenge type is no longer supported by ACME servers.
func (c *Client) TLSSNI01ChallengeCert(token string, opt ...CertOption) (tls.Certificate, string, error)

// TLSSNI02ChallengeCert creates a certificate for the TLS-SNI-02 challenge.
// Deprecated: The TLS-SNI-02 challenge type is no longer supported by ACME servers.
func (c *Client) TLSSNI02ChallengeCert(token string, opt ...CertOption) (tls.Certificate, string, error)

Types

// Account represents a user account.
type Account struct {
    // URI is the account unique ID.
    URI string

    // Contact is a list of contact URLs.
    Contact []string

    // Status indicates the current account status.
    Status string

    // OrdersURL is the URL for listing orders for this account.
    OrdersURL string

    // AgreedTerms indicates the Terms of Service URL the account agreed to.
    AgreedTerms string

    // CurrentTerms is the Terms of Service URL that the account should agree to.
    CurrentTerms string

    // Authz is the URL from which a list of authorizations granted to this account can be fetched.
    Authz string

    // Authorizations is the URL from which a list of authorizations can be fetched.
    Authorizations string

    // Certificates is the URL from which a list of certificates can be fetched.
    Certificates string

    // ExternalAccountBinding represents an external account binding.
    ExternalAccountBinding *ExternalAccountBinding
}

// Authorization represents an authorization response.
type Authorization struct {
    // URI is the authorization unique identifier.
    URI string

    // Status is the current status.
    Status string

    // Identifier is what is being authorized.
    Identifier AuthzID

    // Expires is when the authorization expires.
    Expires time.Time

    // Wildcard indicates whether the authorization is for a wildcard domain.
    Wildcard bool

    // Challenges is the list of challenges that can be used to validate the authorization.
    Challenges []*Challenge

    // Combinations indicates sets of challenges that can be used to validate the authorization.
    Combinations [][]int
}

// AuthorizationError indicates that an authorization failed for a specific identifier.
type AuthorizationError struct {
    // URI is the authorization URL.
    URI string

    // Identifier is the identifier that failed authorization.
    Identifier string

    // Errors are the authorization errors.
    Errors []error
}

func (a *AuthorizationError) Error() string

// AuthzID identifies an authorization request.
type AuthzID struct {
    // Type is the identifier type, e.g. "dns" or "ip".
    Type string

    // Value is the identifier value, e.g. "example.org" or "203.0.113.1".
    Value string
}

// Challenge represents a CA challenge.
type Challenge struct {
    // Type is the challenge type.
    Type string

    // URI is the challenge URL.
    URI string

    // Token is the challenge token.
    Token string

    // Status is the current challenge status.
    Status string

    // Validated is when the challenge was validated.
    Validated time.Time

    // Error is any error that occurred during challenge validation.
    Error error

    // Payload contains type-specific challenge data.
    Payload json.RawMessage
}

// CRLReasonCode identifies the reason for certificate revocation.
type CRLReasonCode int

const (
    CRLReasonUnspecified          CRLReasonCode = 0
    CRLReasonKeyCompromise        CRLReasonCode = 1
    CRLReasonCACompromise         CRLReasonCode = 2
    CRLReasonAffiliationChanged   CRLReasonCode = 3
    CRLReasonSuperseded           CRLReasonCode = 4
    CRLReasonCessationOfOperation CRLReasonCode = 5
    CRLReasonCertificateHold      CRLReasonCode = 6
    CRLReasonRemoveFromCRL        CRLReasonCode = 8
    CRLReasonPrivilegeWithdrawn   CRLReasonCode = 9
    CRLReasonAACompromise         CRLReasonCode = 10
)

// CertOption is an option type for TLS challenge certificate creation.
type CertOption interface {
    // contains unexported methods
}

// Directory represents an ACME server discovery data.
type Directory struct {
    // NonceURL is the URL to fetch a new nonce.
    NonceURL string

    // RegURL is the registration URL.
    RegURL string

    // OrderURL is the URL for creating new orders.
    OrderURL string

    // AuthzURL is the authorization URL.
    AuthzURL string

    // CertURL is the certificate URL.
    CertURL string

    // RevokeURL is the certificate revocation URL.
    RevokeURL string

    // KeyChangeURL is the key rollover URL.
    KeyChangeURL string

    // Terms is the Terms of Service URL.
    Terms string

    // Website is a URL for more information.
    Website string

    // CAA is the list of CAA identities for the ACME server.
    CAA []string

    // ExternalAccountRequired indicates whether external account binding is required.
    ExternalAccountRequired bool
}

// Error represents an ACME error.
type Error struct {
    // StatusCode is the HTTP response status code.
    StatusCode int

    // ProblemType is a URI identifying the type of problem.
    ProblemType string

    // Detail is a human-readable explanation.
    Detail string

    // Instance is a URI identifying the specific occurrence of the problem.
    Instance string

    // Header is the HTTP response header.
    Header http.Header

    // Subproblems are additional, more specific problems.
    Subproblems []Subproblem
}

func (e *Error) Error() string

// ExternalAccountBinding represents external account binding data.
type ExternalAccountBinding struct {
    // KID is the key identifier.
    KID string

    // Key is the MAC key.
    Key []byte
}

func (e *ExternalAccountBinding) String() string

// KeyID is an account key identity.
type KeyID string

// Order represents a certificate order.
type Order struct {
    // URI is the order unique identifier.
    URI string

    // Status is the current order status.
    Status string

    // Expires is when the order expires.
    Expires time.Time

    // Identifiers are the names being requested.
    Identifiers []AuthzID

    // NotBefore is the requested not-before time.
    NotBefore time.Time

    // NotAfter is the requested not-after time.
    NotAfter time.Time

    // Error is any error that occurred during order processing.
    Error *Error

    // Authorizations are the authorization URLs.
    Authorizations []string

    // FinalizeURL is the URL to submit the CSR.
    FinalizeURL string

    // CertURL is the certificate URL once issued.
    CertURL string
}

// OrderError indicates that an order failed.
type OrderError struct {
    // OrderURL is the order URL.
    OrderURL string

    // Status is the order status.
    Status string
}

func (e *OrderError) Error() string

// OrderOption is an option type for order creation.
type OrderOption interface {
    // contains unexported methods
}

// Subproblem represents a detailed error.
type Subproblem struct {
    // Type is the problem type.
    Type string

    // Detail is a human-readable explanation.
    Detail string

    // Identifier is the identifier related to this problem.
    Identifier *AuthzID
}

Helper Functions

// AcceptTOS is a PromptFunc that always returns true.
func AcceptTOS(tosURL string) bool

// JWKThumbprint creates a JWK thumbprint from a public key.
func JWKThumbprint(pub crypto.PublicKey) (string, error)

// RateLimit reports whether err is a rate limit error and
// Retry-After duration returned by the server.
func RateLimit(err error) (time.Duration, bool)

// DomainIDs creates a slice of AuthzID with "dns" identifier type.
func DomainIDs(names ...string) []AuthzID

// IPIDs creates a slice of AuthzID with "ip" identifier type.
func IPIDs(addr ...string) []AuthzID

// WithKey returns a CertOption that uses the provided key pair.
func WithKey(key crypto.Signer) CertOption

// WithTemplate returns a CertOption that uses the provided certificate template.
func WithTemplate(t *x509.Certificate) CertOption

// WithOrderNotBefore returns an OrderOption that sets the NotBefore time.
func WithOrderNotBefore(t time.Time) OrderOption

// WithOrderNotAfter returns an OrderOption that sets the NotAfter time.
func WithOrderNotAfter(t time.Time) OrderOption

Package: golang.org/x/crypto/acme/autocert

Automatic certificate management with Let's Encrypt.

Constants

const DefaultACMEDirectory = "https://acme-v02.api.letsencrypt.org/directory"

Variables

var ErrCacheMiss = errors.New("acme/autocert: certificate cache miss")

Manager

// Manager is a stateful certificate manager.
type Manager struct {
    // Prompt specifies a callback function to accept the CA's Terms of Service.
    // If nil, the default AcceptTOS is used.
    Prompt func(tosURL string) bool

    // Cache optionally stores and retrieves previously obtained certificates.
    Cache Cache

    // HostPolicy controls which domains the Manager will attempt to obtain certificates for.
    // If nil, all domains are allowed.
    HostPolicy HostPolicy

    // RenewBefore optionally specifies how long before expiry a certificate should be renewed.
    // Default is 30 days.
    RenewBefore time.Duration

    // Client is the ACME client used to obtain certificates.
    // If nil, a default client is used.
    Client *acme.Client

    // Email optionally specifies a contact email address.
    Email string

    // ForceRSA makes the Manager generate RSA certificates instead of ECDSA.
    // Deprecated: The Manager will automatically generate either RSA or ECDSA certificates.
    ForceRSA bool

    // ExtraExtensions are additional extensions to include in certificate requests.
    ExtraExtensions []pkix.Extension

    // ExternalAccountBinding optionally represents external account credentials.
    ExternalAccountBinding *acme.ExternalAccountBinding
}

// GetCertificate implements the tls.Config.GetCertificate hook.
func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, error)

// TLSConfig creates a TLS config suitable for use with the Manager.
func (m *Manager) TLSConfig() *tls.Config

// Listener returns a net.Listener that listens on port 443 and automatically obtains certificates.
func (m *Manager) Listener() net.Listener

// HTTPHandler creates an http.Handler that handles ACME HTTP-01 challenges.
func (m *Manager) HTTPHandler(fallback http.Handler) http.Handler

Cache Interface

// Cache is used to store and retrieve certificates.
type Cache interface {
    // Get returns a certificate data for the specified key.
    Get(ctx context.Context, key string) ([]byte, error)

    // Put stores the certificate data in the cache under the specified key.
    Put(ctx context.Context, key string, data []byte) error

    // Delete removes a certificate data from the cache under the specified key.
    Delete(ctx context.Context, key string) error
}

// DirCache implements Cache using a directory on the local filesystem.
type DirCache string

func (d DirCache) Get(ctx context.Context, name string) ([]byte, error)
func (d DirCache) Put(ctx context.Context, name string, data []byte) error
func (d DirCache) Delete(ctx context.Context, name string) error

Host Policy

// HostPolicy is a function that determines whether the Manager should obtain a certificate for the given host.
type HostPolicy func(ctx context.Context, host string) error

// HostWhitelist returns a HostPolicy that only allows the specified hosts.
func HostWhitelist(hosts ...string) HostPolicy

Helper Functions

// AcceptTOS is a PromptFunc that always returns true.
func AcceptTOS(tosURL string) bool

// NewListener returns a net.Listener that listens on TCP port 443
// and automatically obtains certificates for the given domains.
func NewListener(domains ...string) net.Listener

Usage Examples

Basic ACME Client

package main

import (
    "context"
    "crypto/ecdsa"
    "crypto/elliptic"
    "crypto/rand"
    "crypto/x509"
    "crypto/x509/pkix"
    "golang.org/x/crypto/acme"
)

func main() {
    // Create account key
    accountKey, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)

    // Create ACME client
    client := &acme.Client{
        Key:          accountKey,
        DirectoryURL: acme.LetsEncryptURL,
    }

    // Register account
    account := &acme.Account{
        Contact: []string{"mailto:admin@example.com"},
    }
    account, _ = client.Register(context.Background(), account, acme.AcceptTOS)

    // Create order for domain
    order, _ := client.AuthorizeOrder(context.Background(), acme.DomainIDs("example.com"))

    // Get authorization
    authz, _ := client.GetAuthorization(context.Background(), order.Authorizations[0])

    // Find HTTP-01 challenge
    var httpChallenge *acme.Challenge
    for _, c := range authz.Challenges {
        if c.Type == "http-01" {
            httpChallenge = c
            break
        }
    }

    // Set up HTTP challenge response
    path := client.HTTP01ChallengePath(httpChallenge.Token)
    response, _ := client.HTTP01ChallengeResponse(httpChallenge.Token)
    // Serve response at /.well-known/acme-challenge/{token}

    // Accept challenge
    client.Accept(context.Background(), httpChallenge)

    // Wait for order to be ready
    order, _ = client.WaitOrder(context.Background(), order.URI)

    // Create CSR
    certKey, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
    template := &x509.CertificateRequest{
        Subject: pkix.Name{CommonName: "example.com"},
    }
    csr, _ := x509.CreateCertificateRequest(rand.Reader, template, certKey)

    // Finalize order and get certificate
    der, certURL, _ := client.CreateOrderCert(context.Background(), order.FinalizeURL, csr, true)

    // Parse certificate
    cert, _ := x509.ParseCertificate(der[0])
}

Automatic Certificate Management

package main

import (
    "crypto/tls"
    "net/http"
    "golang.org/x/crypto/acme/autocert"
)

func main() {
    // Create manager with cache
    m := &autocert.Manager{
        Cache:      autocert.DirCache("certs"),
        Prompt:     autocert.AcceptTOS,
        HostPolicy: autocert.HostWhitelist("example.com", "www.example.com"),
        Email:      "admin@example.com",
    }

    // Create HTTP server with automatic HTTPS
    server := &http.Server{
        Addr:      ":https",
        TLSConfig: m.TLSConfig(),
    }

    // Start HTTP-01 challenge handler
    go http.ListenAndServe(":http", m.HTTPHandler(nil))

    // Start HTTPS server
    server.ListenAndServeTLS("", "")
}

Simple Listener

package main

import (
    "net/http"
    "golang.org/x/crypto/acme/autocert"
)

func main() {
    // Create listener that automatically obtains certificates
    listener := autocert.NewListener("example.com")

    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte("Hello, TLS!"))
    })

    http.Serve(listener, nil)
}