// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package acmetest provides types for testing acme and autocert packages.
//
// TODO: Consider moving this to x/crypto/acme/internal/acmetest for acme tests as well.
package acmetest

import (
	"context"
	"crypto"
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/rand"
	"crypto/rsa"
	"crypto/tls"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/asn1"
	"encoding/base64"
	"encoding/json"
	"encoding/pem"
	"fmt"
	"io"
	"math/big"
	"net"
	"net/http"
	"net/http/httptest"
	"path"
	"strconv"
	"strings"
	"sync"
	"testing"
	"time"

	"golang.org/x/crypto/acme"
)

// CAServer is a simple test server which implements ACME spec bits needed for testing.
type CAServer struct {
	rootKey      crypto.Signer
	rootCert     []byte // DER encoding
	rootTemplate *x509.Certificate

	t              *testing.T
	server         *httptest.Server
	issuer         pkix.Name
	challengeTypes []string
	url            string
	roots          *x509.CertPool

	mu             sync.Mutex
	certCount      int                           // number of issued certs
	acctRegistered bool                          // set once an account has been registered
	domainAddr     map[string]string             // domain name to addr:port resolution
	domainGetCert  map[string]getCertificateFunc // domain name to GetCertificate function
	domainHandler  map[string]http.Handler       // domain name to Handle function
	validAuthz     map[string]*authorization     // valid authz, keyed by domain name
	authorizations []*authorization              // all authz, index is used as ID
	orders         []*order                      // index is used as order ID
	errors         []error                       // encountered client errors
}

type getCertificateFunc func(hello *tls.ClientHelloInfo) (*tls.Certificate, error)

// NewCAServer creates a new ACME test server. The returned CAServer issues
// certs signed with the CA roots available in the Roots field.
func NewCAServer(t *testing.T) *CAServer {
	ca := &CAServer{t: t,
		challengeTypes: []string{"fake-01", "tls-alpn-01", "http-01"},
		domainAddr:     make(map[string]string),
		domainGetCert:  make(map[string]getCertificateFunc),
		domainHandler:  make(map[string]http.Handler),
		validAuthz:     make(map[string]*authorization),
	}

	ca.server = httptest.NewUnstartedServer(http.HandlerFunc(ca.handle))

	r, err := rand.Int(rand.Reader, big.NewInt(1000000))
	if err != nil {
		panic(fmt.Sprintf("rand.Int: %v", err))
	}
	ca.issuer = pkix.Name{
		Organization: []string{"Test Acme Co"},
		CommonName:   "Root CA " + r.String(),
	}

	return ca
}

func (ca *CAServer) generateRoot() {
	key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
	if err != nil {
		panic(fmt.Sprintf("ecdsa.GenerateKey: %v", err))
	}
	tmpl := &x509.Certificate{
		SerialNumber:          big.NewInt(1),
		Subject:               ca.issuer,
		NotBefore:             time.Now(),
		NotAfter:              time.Now().Add(365 * 24 * time.Hour),
		KeyUsage:              x509.KeyUsageCertSign,
		BasicConstraintsValid: true,
		IsCA:                  true,
	}
	der, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &key.PublicKey, key)
	if err != nil {
		panic(fmt.Sprintf("x509.CreateCertificate: %v", err))
	}
	cert, err := x509.ParseCertificate(der)
	if err != nil {
		panic(fmt.Sprintf("x509.ParseCertificate: %v", err))
	}
	ca.roots = x509.NewCertPool()
	ca.roots.AddCert(cert)
	ca.rootKey = key
	ca.rootCert = der
	ca.rootTemplate = tmpl
}

// IssuerName sets the name of the issuing CA.
func (ca *CAServer) IssuerName(name pkix.Name) *CAServer {
	if ca.url != "" {
		panic("IssuerName must be called before Start")
	}
	ca.issuer = name
	return ca
}

// ChallengeTypes sets the supported challenge types.
func (ca *CAServer) ChallengeTypes(types ...string) *CAServer {
	if ca.url != "" {
		panic("ChallengeTypes must be called before Start")
	}
	ca.challengeTypes = types
	return ca
}

// URL returns the server address, after Start has been called.
func (ca *CAServer) URL() string {
	if ca.url == "" {
		panic("URL called before Start")
	}
	return ca.url
}

// Roots returns a pool cointaining the CA root.
func (ca *CAServer) Roots() *x509.CertPool {
	if ca.url == "" {
		panic("Roots called before Start")
	}
	return ca.roots
}

// Start starts serving requests. The server address becomes available in the
// URL field.
func (ca *CAServer) Start() *CAServer {
	if ca.url == "" {
		ca.generateRoot()
		ca.server.Start()
		ca.t.Cleanup(ca.server.Close)
		ca.url = ca.server.URL
	}
	return ca
}

func (ca *CAServer) serverURL(format string, arg ...interface{}) string {
	return ca.server.URL + fmt.Sprintf(format, arg...)
}

func (ca *CAServer) addr(domain string) (string, bool) {
	ca.mu.Lock()
	defer ca.mu.Unlock()
	addr, ok := ca.domainAddr[domain]
	return addr, ok
}

func (ca *CAServer) getCert(domain string) (getCertificateFunc, bool) {
	ca.mu.Lock()
	defer ca.mu.Unlock()
	f, ok := ca.domainGetCert[domain]
	return f, ok
}

func (ca *CAServer) getHandler(domain string) (http.Handler, bool) {
	ca.mu.Lock()
	defer ca.mu.Unlock()
	h, ok := ca.domainHandler[domain]
	return h, ok
}

func (ca *CAServer) httpErrorf(w http.ResponseWriter, code int, format string, a ...interface{}) {
	s := fmt.Sprintf(format, a...)
	ca.t.Errorf(format, a...)
	http.Error(w, s, code)
}

// Resolve adds a domain to address resolution for the ca to dial to
// when validating challenges for the domain authorization.
func (ca *CAServer) Resolve(domain, addr string) {
	ca.mu.Lock()
	defer ca.mu.Unlock()
	ca.domainAddr[domain] = addr
}

// ResolveGetCertificate redirects TLS connections for domain to f when
// validating challenges for the domain authorization.
func (ca *CAServer) ResolveGetCertificate(domain string, f getCertificateFunc) {
	ca.mu.Lock()
	defer ca.mu.Unlock()
	ca.domainGetCert[domain] = f
}

// ResolveHandler redirects HTTP requests for domain to f when
// validating challenges for the domain authorization.
func (ca *CAServer) ResolveHandler(domain string, h http.Handler) {
	ca.mu.Lock()
	defer ca.mu.Unlock()
	ca.domainHandler[domain] = h
}

type discovery struct {
	NewNonce string `json:"newNonce"`
	NewReg   string `json:"newAccount"`
	NewOrder string `json:"newOrder"`
	NewAuthz string `json:"newAuthz"`
}

type challenge struct {
	URI   string `json:"uri"`
	Type  string `json:"type"`
	Token string `json:"token"`
}

type authorization struct {
	Status     string      `json:"status"`
	Challenges []challenge `json:"challenges"`

	domain string
	id     int
}

type order struct {
	Status      string   `json:"status"`
	AuthzURLs   []string `json:"authorizations"`
	FinalizeURL string   `json:"finalize"`    // CSR submit URL
	CertURL     string   `json:"certificate"` // already issued cert

	leaf []byte // issued cert in DER format
}

func (ca *CAServer) handle(w http.ResponseWriter, r *http.Request) {
	ca.t.Logf("%s %s", r.Method, r.URL)
	w.Header().Set("Replay-Nonce", "nonce")
	// TODO: Verify nonce header for all POST requests.

	switch {
	default:
		ca.httpErrorf(w, http.StatusBadRequest, "unrecognized r.URL.Path: %s", r.URL.Path)

	// Discovery request.
	case r.URL.Path == "/":
		resp := &discovery{
			NewNonce: ca.serverURL("/new-nonce"),
			NewReg:   ca.serverURL("/new-reg"),
			NewOrder: ca.serverURL("/new-order"),
		}
		if err := json.NewEncoder(w).Encode(resp); err != nil {
			panic(fmt.Sprintf("discovery response: %v", err))
		}

	// Nonce requests.
	case r.URL.Path == "/new-nonce":
		// Nonce values are always set. Nothing else to do.
		return

	// Client key registration request.
	case r.URL.Path == "/new-reg":
		ca.mu.Lock()
		defer ca.mu.Unlock()
		if ca.acctRegistered {
			ca.httpErrorf(w, http.StatusServiceUnavailable, "multiple accounts are not implemented")
			return
		}
		ca.acctRegistered = true
		// TODO: Check the user account key against a ca.accountKeys?
		w.Header().Set("Location", ca.serverURL("/accounts/1"))
		w.WriteHeader(http.StatusCreated)
		w.Write([]byte("{}"))

	// New order request.
	case r.URL.Path == "/new-order":
		var req struct {
			Identifiers []struct{ Value string }
		}
		if err := decodePayload(&req, r.Body); err != nil {
			ca.httpErrorf(w, http.StatusBadRequest, err.Error())
			return
		}
		ca.mu.Lock()
		defer ca.mu.Unlock()
		o := &order{Status: acme.StatusPending}
		for _, id := range req.Identifiers {
			z := ca.authz(id.Value)
			o.AuthzURLs = append(o.AuthzURLs, ca.serverURL("/authz/%d", z.id))
		}
		orderID := len(ca.orders)
		ca.orders = append(ca.orders, o)
		w.Header().Set("Location", ca.serverURL("/orders/%d", orderID))
		w.WriteHeader(http.StatusCreated)
		if err := json.NewEncoder(w).Encode(o); err != nil {
			panic(err)
		}

	// Existing order status requests.
	case strings.HasPrefix(r.URL.Path, "/orders/"):
		ca.mu.Lock()
		defer ca.mu.Unlock()
		o, err := ca.storedOrder(strings.TrimPrefix(r.URL.Path, "/orders/"))
		if err != nil {
			ca.httpErrorf(w, http.StatusBadRequest, err.Error())
			return
		}
		if err := json.NewEncoder(w).Encode(o); err != nil {
			panic(err)
		}

	// Accept challenge requests.
	case strings.HasPrefix(r.URL.Path, "/challenge/"):
		parts := strings.Split(r.URL.Path, "/")
		typ, id := parts[len(parts)-2], parts[len(parts)-1]
		ca.mu.Lock()
		supported := false
		for _, suppTyp := range ca.challengeTypes {
			if suppTyp == typ {
				supported = true
			}
		}
		a, err := ca.storedAuthz(id)
		ca.mu.Unlock()
		if !supported {
			ca.httpErrorf(w, http.StatusBadRequest, "unsupported challenge: %v", typ)
			return
		}
		if err != nil {
			ca.httpErrorf(w, http.StatusBadRequest, "challenge accept: %v", err)
			return
		}
		go ca.validateChallenge(a, typ)
		w.Write([]byte("{}"))

	// Get authorization status requests.
	case strings.HasPrefix(r.URL.Path, "/authz/"):
		var req struct{ Status string }
		decodePayload(&req, r.Body)
		deactivate := req.Status == "deactivated"
		ca.mu.Lock()
		defer ca.mu.Unlock()
		authz, err := ca.storedAuthz(strings.TrimPrefix(r.URL.Path, "/authz/"))
		if err != nil {
			ca.httpErrorf(w, http.StatusNotFound, "%v", err)
			return
		}
		if deactivate {
			// Note we don't invalidate authorized orders as we should.
			authz.Status = "deactivated"
			ca.t.Logf("authz %d is now %s", authz.id, authz.Status)
		}
		if err := json.NewEncoder(w).Encode(authz); err != nil {
			panic(fmt.Sprintf("encoding authz %d: %v", authz.id, err))
		}

	// Certificate issuance request.
	case strings.HasPrefix(r.URL.Path, "/new-cert/"):
		ca.mu.Lock()
		defer ca.mu.Unlock()
		orderID := strings.TrimPrefix(r.URL.Path, "/new-cert/")
		o, err := ca.storedOrder(orderID)
		if err != nil {
			ca.httpErrorf(w, http.StatusBadRequest, err.Error())
			return
		}
		if o.Status != acme.StatusReady {
			ca.httpErrorf(w, http.StatusForbidden, "order status: %s", o.Status)
			return
		}
		// Validate CSR request.
		var req struct {
			CSR string `json:"csr"`
		}
		decodePayload(&req, r.Body)
		b, _ := base64.RawURLEncoding.DecodeString(req.CSR)
		csr, err := x509.ParseCertificateRequest(b)
		if err != nil {
			ca.httpErrorf(w, http.StatusBadRequest, err.Error())
			return
		}
		// Issue the certificate.
		der, err := ca.leafCert(csr)
		if err != nil {
			ca.httpErrorf(w, http.StatusBadRequest, "new-cert response: ca.leafCert: %v", err)
			return
		}
		o.leaf = der
		o.CertURL = ca.serverURL("/issued-cert/%s", orderID)
		o.Status = acme.StatusValid
		if err := json.NewEncoder(w).Encode(o); err != nil {
			panic(err)
		}

	// Already issued cert download requests.
	case strings.HasPrefix(r.URL.Path, "/issued-cert/"):
		ca.mu.Lock()
		defer ca.mu.Unlock()
		o, err := ca.storedOrder(strings.TrimPrefix(r.URL.Path, "/issued-cert/"))
		if err != nil {
			ca.httpErrorf(w, http.StatusBadRequest, err.Error())
			return
		}
		if o.Status != acme.StatusValid {
			ca.httpErrorf(w, http.StatusForbidden, "order status: %s", o.Status)
			return
		}
		w.Header().Set("Content-Type", "application/pem-certificate-chain")
		pem.Encode(w, &pem.Block{Type: "CERTIFICATE", Bytes: o.leaf})
		pem.Encode(w, &pem.Block{Type: "CERTIFICATE", Bytes: ca.rootCert})
	}
}

// storedOrder retrieves a previously created order at index i.
// It requires ca.mu to be locked.
func (ca *CAServer) storedOrder(i string) (*order, error) {
	idx, err := strconv.Atoi(i)
	if err != nil {
		return nil, fmt.Errorf("storedOrder: %v", err)
	}
	if idx < 0 {
		return nil, fmt.Errorf("storedOrder: invalid order index %d", idx)
	}
	if idx > len(ca.orders)-1 {
		return nil, fmt.Errorf("storedOrder: no such order %d", idx)
	}
	return ca.orders[idx], nil
}

// storedAuthz retrieves a previously created authz at index i.
// It requires ca.mu to be locked.
func (ca *CAServer) storedAuthz(i string) (*authorization, error) {
	idx, err := strconv.Atoi(i)
	if err != nil {
		return nil, fmt.Errorf("storedAuthz: %v", err)
	}
	if idx < 0 {
		return nil, fmt.Errorf("storedAuthz: invalid authz index %d", idx)
	}
	if idx > len(ca.authorizations)-1 {
		return nil, fmt.Errorf("storedAuthz: no such authz %d", idx)
	}
	return ca.authorizations[idx], nil
}

// authz returns an existing valid authorization for the identifier or creates a
// new one. It requires ca.mu to be locked.
func (ca *CAServer) authz(identifier string) *authorization {
	authz, ok := ca.validAuthz[identifier]
	if !ok {
		authzId := len(ca.authorizations)
		authz = &authorization{
			id:     authzId,
			domain: identifier,
			Status: acme.StatusPending,
		}
		for _, typ := range ca.challengeTypes {
			authz.Challenges = append(authz.Challenges, challenge{
				Type:  typ,
				URI:   ca.serverURL("/challenge/%s/%d", typ, authzId),
				Token: challengeToken(authz.domain, typ, authzId),
			})
		}
		ca.authorizations = append(ca.authorizations, authz)
	}
	return authz
}

// leafCert issues a new certificate.
// It requires ca.mu to be locked.
func (ca *CAServer) leafCert(csr *x509.CertificateRequest) (der []byte, err error) {
	ca.certCount++ // next leaf cert serial number
	leaf := &x509.Certificate{
		SerialNumber:          big.NewInt(int64(ca.certCount)),
		Subject:               pkix.Name{Organization: []string{"Test Acme Co"}},
		NotBefore:             time.Now(),
		NotAfter:              time.Now().Add(90 * 24 * time.Hour),
		KeyUsage:              x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment,
		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
		DNSNames:              csr.DNSNames,
		BasicConstraintsValid: true,
	}
	if len(csr.DNSNames) == 0 {
		leaf.DNSNames = []string{csr.Subject.CommonName}
	}
	return x509.CreateCertificate(rand.Reader, leaf, ca.rootTemplate, csr.PublicKey, ca.rootKey)
}

// LeafCert issues a leaf certificate.
func (ca *CAServer) LeafCert(name, keyType string, notBefore, notAfter time.Time) *tls.Certificate {
	if ca.url == "" {
		panic("LeafCert called before Start")
	}

	ca.mu.Lock()
	defer ca.mu.Unlock()
	var pk crypto.Signer
	switch keyType {
	case "RSA":
		var err error
		pk, err = rsa.GenerateKey(rand.Reader, 1024)
		if err != nil {
			ca.t.Fatal(err)
		}
	case "ECDSA":
		var err error
		pk, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
		if err != nil {
			ca.t.Fatal(err)
		}
	default:
		panic("LeafCert: unknown key type")
	}
	ca.certCount++ // next leaf cert serial number
	leaf := &x509.Certificate{
		SerialNumber:          big.NewInt(int64(ca.certCount)),
		Subject:               pkix.Name{Organization: []string{"Test Acme Co"}},
		NotBefore:             notBefore,
		NotAfter:              notAfter,
		KeyUsage:              x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment,
		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
		DNSNames:              []string{name},
		BasicConstraintsValid: true,
	}
	der, err := x509.CreateCertificate(rand.Reader, leaf, ca.rootTemplate, pk.Public(), ca.rootKey)
	if err != nil {
		ca.t.Fatal(err)
	}
	return &tls.Certificate{
		Certificate: [][]byte{der},
		PrivateKey:  pk,
	}
}

func (ca *CAServer) validateChallenge(authz *authorization, typ string) {
	var err error
	switch typ {
	case "tls-alpn-01":
		err = ca.verifyALPNChallenge(authz)
	case "http-01":
		err = ca.verifyHTTPChallenge(authz)
	default:
		panic(fmt.Sprintf("validation of %q is not implemented", typ))
	}
	ca.mu.Lock()
	defer ca.mu.Unlock()
	if err != nil {
		authz.Status = "invalid"
	} else {
		authz.Status = "valid"
		ca.validAuthz[authz.domain] = authz
	}
	ca.t.Logf("validated %q for %q, err: %v", typ, authz.domain, err)
	ca.t.Logf("authz %d is now %s", authz.id, authz.Status)
	// Update all pending orders.
	// An order becomes "ready" if all authorizations are "valid".
	// An order becomes "invalid" if any authorization is "invalid".
	// Status changes: https://tools.ietf.org/html/rfc8555#section-7.1.6
OrdersLoop:
	for i, o := range ca.orders {
		if o.Status != acme.StatusPending {
			continue
		}
		var countValid int
		for _, zurl := range o.AuthzURLs {
			z, err := ca.storedAuthz(path.Base(zurl))
			if err != nil {
				ca.t.Logf("no authz %q for order %d", zurl, i)
				continue OrdersLoop
			}
			if z.Status == acme.StatusInvalid {
				o.Status = acme.StatusInvalid
				ca.t.Logf("order %d is now invalid", i)
				continue OrdersLoop
			}
			if z.Status == acme.StatusValid {
				countValid++
			}
		}
		if countValid == len(o.AuthzURLs) {
			o.Status = acme.StatusReady
			o.FinalizeURL = ca.serverURL("/new-cert/%d", i)
			ca.t.Logf("order %d is now ready", i)
		}
	}
}

func (ca *CAServer) verifyALPNChallenge(a *authorization) error {
	const acmeALPNProto = "acme-tls/1"

	addr, haveAddr := ca.addr(a.domain)
	getCert, haveGetCert := ca.getCert(a.domain)
	if !haveAddr && !haveGetCert {
		return fmt.Errorf("no resolution information for %q", a.domain)
	}
	if haveAddr && haveGetCert {
		return fmt.Errorf("overlapping resolution information for %q", a.domain)
	}

	var crt *x509.Certificate
	switch {
	case haveAddr:
		conn, err := tls.Dial("tcp", addr, &tls.Config{
			ServerName:         a.domain,
			InsecureSkipVerify: true,
			NextProtos:         []string{acmeALPNProto},
			MinVersion:         tls.VersionTLS12,
		})
		if err != nil {
			return err
		}
		if v := conn.ConnectionState().NegotiatedProtocol; v != acmeALPNProto {
			return fmt.Errorf("CAServer: verifyALPNChallenge: negotiated proto is %q; want %q", v, acmeALPNProto)
		}
		if n := len(conn.ConnectionState().PeerCertificates); n != 1 {
			return fmt.Errorf("len(PeerCertificates) = %d; want 1", n)
		}
		crt = conn.ConnectionState().PeerCertificates[0]
	case haveGetCert:
		hello := &tls.ClientHelloInfo{
			ServerName: a.domain,
			// TODO: support selecting ECDSA.
			CipherSuites:      []uint16{tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305},
			SupportedProtos:   []string{acme.ALPNProto},
			SupportedVersions: []uint16{tls.VersionTLS12},
		}
		c, err := getCert(hello)
		if err != nil {
			return err
		}
		crt, err = x509.ParseCertificate(c.Certificate[0])
		if err != nil {
			return err
		}
	}

	if err := crt.VerifyHostname(a.domain); err != nil {
		return fmt.Errorf("verifyALPNChallenge: VerifyHostname: %v", err)
	}
	// See RFC 8737, Section 6.1.
	oid := asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 31}
	for _, x := range crt.Extensions {
		if x.Id.Equal(oid) {
			// TODO: check the token.
			return nil
		}
	}
	return fmt.Errorf("verifyTokenCert: no id-pe-acmeIdentifier extension found")
}

func (ca *CAServer) verifyHTTPChallenge(a *authorization) error {
	addr, haveAddr := ca.addr(a.domain)
	handler, haveHandler := ca.getHandler(a.domain)
	if !haveAddr && !haveHandler {
		return fmt.Errorf("no resolution information for %q", a.domain)
	}
	if haveAddr && haveHandler {
		return fmt.Errorf("overlapping resolution information for %q", a.domain)
	}

	token := challengeToken(a.domain, "http-01", a.id)
	path := "/.well-known/acme-challenge/" + token

	var body string
	switch {
	case haveAddr:
		t := &http.Transport{
			DialContext: func(ctx context.Context, network, _ string) (net.Conn, error) {
				return (&net.Dialer{}).DialContext(ctx, network, addr)
			},
		}
		req, err := http.NewRequest("GET", "http://"+a.domain+path, nil)
		if err != nil {
			return err
		}
		res, err := t.RoundTrip(req)
		if err != nil {
			return err
		}
		if res.StatusCode != http.StatusOK {
			return fmt.Errorf("http token: w.Code = %d; want %d", res.StatusCode, http.StatusOK)
		}
		b, err := io.ReadAll(res.Body)
		if err != nil {
			return err
		}
		body = string(b)
	case haveHandler:
		r := httptest.NewRequest("GET", path, nil)
		r.Host = a.domain
		w := httptest.NewRecorder()
		handler.ServeHTTP(w, r)
		if w.Code != http.StatusOK {
			return fmt.Errorf("http token: w.Code = %d; want %d", w.Code, http.StatusOK)
		}
		body = w.Body.String()
	}

	if !strings.HasPrefix(body, token) {
		return fmt.Errorf("http token value = %q; want 'token-http-01.' prefix", body)
	}
	return nil
}

func decodePayload(v interface{}, r io.Reader) error {
	var req struct{ Payload string }
	if err := json.NewDecoder(r).Decode(&req); err != nil {
		return err
	}
	payload, err := base64.RawURLEncoding.DecodeString(req.Payload)
	if err != nil {
		return err
	}
	return json.Unmarshal(payload, v)
}

func challengeToken(domain, challType string, authzID int) string {
	return fmt.Sprintf("token-%s-%s-%d", domain, challType, authzID)
}

func unique(a []string) []string {
	seen := make(map[string]bool)
	var res []string
	for _, s := range a {
		if s != "" && !seen[s] {
			seen[s] = true
			res = append(res, s)
		}
	}
	return res
}
