Repository: go-acme/lego
Pull request #2066 (2023-12-06 17:47:49)

Update CertID format as per draft-ietf-acme-ari-02
- Implemented the updated CertID format as specified in draft-ietf-acme-ari-02.
- Removed the `--ari-hash-name` flag, which is no longer necessary with the updated format.
- Enabled ARI usage for users with `--no-bundle` option. Previously, this was not possible as the draft-ietf-acme-ari-01 format required metadata available only in the issuer.

---

ATTENTION: this must NOT be merged and should remain in draft until https://github.com/letsencrypt/boulder/pull/7184 is merged and deployed.

UPDATE: this change has been merged, but it will not be deployed to Production until a few days into the new year. I'll update this issue when that's the case.

beautifulentropy: Failing test:

```
Error: cmd/cmd_renew.go:128:1: cyclomatic complexity 15 of func `renewForDomains` is high (> 12) (gocyclo)
func renewForDomains(ctx *cli.Context, client *lego.Client, certsStorage *CertificatesStorage, bundle bool, meta map[string]string) error {
^
make: *** [Makefile:36: checks] Error 1
Error: Process completed with exit code 2.
```
ldez: for now, you can ignore the linter about cyclomatic complexity, I will look at the best way to handle that.
ldez: I fixed the problem of cyclomatic complexity.
Just waiting for the deployment to Production.
beautifulentropy: > I fixed the problem of cyclomatic complexity. Just waiting for the deployment to Production.

Thanks for fixing this. Just checked our SRE team and support for this portion of draft-ietf-acme-ari-02 has been successfully deployed to both staging and production.
ldez: Maybe you can set the PR as "Ready for review"?


Patch:
diff --git a/.golangci.yml b/.golangci.yml
index 03bf1f99..c00b6c4a 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -236,4 +236,4 @@ issues:
     - path: providers/dns/hosttech/internal/client_test.go
       text: 'Duplicate words \(0\) found'
     - path: cmd/cmd_renew.go
-      text: 'cyclomatic complexity 16 of func `renewForDomains` is high'
+      text: 'cyclomatic complexity 15 of func `renewForDomains` is high'
diff --git a/README.md b/README.md
index d0df0bec..213ae89b 100644
--- a/README.md
+++ b/README.md
@@ -16,7 +16,7 @@ Let's Encrypt client and ACME library written in Go.
 - ACME v2 [RFC 8555](https://www.rfc-editor.org/rfc/rfc8555.html)
   - Support [RFC 8737](https://www.rfc-editor.org/rfc/rfc8737.html): TLS Application‑Layer Protocol Negotiation (ALPN) Challenge Extension
   - Support [RFC 8738](https://www.rfc-editor.org/rfc/rfc8738.html): certificates for IP addresses
-  - Support [draft-ietf-acme-ari-01](https://datatracker.ietf.org/doc/draft-ietf-acme-ari/): Renewal Information (ARI) Extension
+  - Support [draft-ietf-acme-ari-02](https://datatracker.ietf.org/doc/draft-ietf-acme-ari/): Renewal Information (ARI) Extension
 - Register with CA
 - Obtain certificates, both from scratch or with an existing CSR
 - Renew certificates
diff --git a/acme/commons.go b/acme/commons.go
index 03b5db6d..70b2783d 100644
--- a/acme/commons.go
+++ b/acme/commons.go
@@ -329,9 +329,11 @@ type RenewalInfoResponse struct {
 }
 
 // RenewalInfoUpdateRequest is the JWS payload for POST requests made to the renewalInfo endpoint.
-// - (4.2. Updating Renewal Information) https://datatracker.ietf.org/doc/draft-ietf-acme-ari/
+// - (4.2. RenewalInfo Objects) https://datatracker.ietf.org/doc/html/draft-ietf-acme-ari-02#section-4.2
 type RenewalInfoUpdateRequest struct {
-	// CertID is the base64url-encoded [RFC4648] bytes of a DER-encoded CertID ASN.1 sequence [RFC6960] with any trailing '=' characters stripped.
+	// CertID is a composite string in the format: base64url(AKI) || '.' || base64url(Serial), where AKI is the
+	// certificate's authority key identifier and Serial is the certificate's serial number. For details, see:
+	// https://datatracker.ietf.org/doc/html/draft-ietf-acme-ari-02#section-4.1
 	CertID string `json:"certID"`
 	// Replaced is required and indicates whether or not the client considers the certificate to have been replaced.
 	// A certificate is considered replaced when its revocation would not disrupt any ongoing services,
diff --git a/certificate/renewal.go b/certificate/renewal.go
index 26160672..314cd3ea 100644
--- a/certificate/renewal.go
+++ b/certificate/renewal.go
@@ -1,14 +1,11 @@
 package certificate
 
 import (
-	"crypto"
 	"crypto/x509"
-	"crypto/x509/pkix"
-	"encoding/asn1"
 	"encoding/base64"
 	"encoding/json"
+	"errors"
 	"fmt"
-	"math/big"
 	"math/rand"
 	"strings"
 	"time"
@@ -18,11 +15,7 @@ import (
 
 // RenewalInfoRequest contains the necessary renewal information.
 type RenewalInfoRequest struct {
-	Cert   *x509.Certificate
-	Issuer *x509.Certificate
-	// HashName must be the string representation of a crypto.Hash constant in the golang.org/x/crypto package (e.g. "SHA-256").
-	// The correct value depends on the algorithm expected by the ACME server's ARI implementation.
-	HashName string
+	Cert *x509.Certificate
 }
 
 // RenewalInfoResponse is a wrapper around acme.RenewalInfoResponse that provides a method for determining when to renew a certificate.
@@ -72,7 +65,7 @@ func (r *RenewalInfoResponse) ShouldRenewAt(now time.Time, willingToSleep time.D
 //
 // https://datatracker.ietf.org/doc/draft-ietf-acme-ari
 func (c *Certifier) GetRenewalInfo(req RenewalInfoRequest) (*RenewalInfoResponse, error) {
-	certID, err := makeCertID(req.Cert, req.Issuer, req.HashName)
+	certID, err := makeARICertID(req.Cert)
 	if err != nil {
 		return nil, fmt.Errorf("error making certID: %w", err)
 	}
@@ -100,7 +93,7 @@ func (c *Certifier) GetRenewalInfo(req RenewalInfoRequest) (*RenewalInfoResponse
 //
 // https://datatracker.ietf.org/doc/draft-ietf-acme-ari
 func (c *Certifier) UpdateRenewalInfo(req RenewalInfoRequest) error {
-	certID, err := makeCertID(req.Cert, req.Issuer, req.HashName)
+	certID, err := makeARICertID(req.Cert)
 	if err != nil {
 		return fmt.Errorf("error making certID: %w", err)
 	}
@@ -116,89 +109,14 @@ func (c *Certifier) UpdateRenewalInfo(req RenewalInfoRequest) error {
 	return nil
 }
 
-// makeCertID returns a base64url-encoded string that uniquely identifies a certificate to endpoints
-// that implement the draft-ietf-acme-ari specification: https://datatracker.ietf.org/doc/draft-ietf-acme-ari.
-// hashName must be the string representation of a crypto.Hash constant in the golang.org/x/crypto package.
-// Supported hash functions are SHA-1, SHA-256, SHA-384, and SHA-512.
-func makeCertID(leaf, issuer *x509.Certificate, hashName string) (string, error) {
+// makeARICertID constructs a certificate identifier as described in draft-ietf-acme-ari-02, section 4.1.
+func makeARICertID(leaf *x509.Certificate) (string, error) {
 	if leaf == nil {
-		return "", fmt.Errorf("leaf certificate is nil")
+		return "", errors.New("leaf certificate is nil")
 	}
-	if issuer == nil {
-		return "", fmt.Errorf("issuer certificate is nil")
-	}
-
-	var hashFunc crypto.Hash
-	var oid asn1.ObjectIdentifier
-
-	switch hashName {
-	// The following correlation of hashFunc to OID is copied from a private mapping in golang.org/x/crypto/ocsp:
-	// https://cs.opensource.google/go/x/crypto/+/refs/tags/v0.8.0:ocsp/ocsp.go;l=156
-	case crypto.SHA1.String():
-		hashFunc = crypto.SHA1
-		oid = asn1.ObjectIdentifier([]int{1, 3, 14, 3, 2, 26})
-
-	case crypto.SHA256.String():
-		hashFunc = crypto.SHA256
-		oid = asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 1})
-
-	case crypto.SHA384.String():
-		hashFunc = crypto.SHA384
-		oid = asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 2})
-
-	case crypto.SHA512.String():
-		hashFunc = crypto.SHA512
-		oid = asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 3})
-
-	default:
-		return "", fmt.Errorf("hashName %q is not supported by this package", hashName)
-	}
-
-	if !hashFunc.Available() {
-		// This should never happen.
-		return "", fmt.Errorf("hash function %q is not available on your platform", hashFunc)
-	}
-
-	var spki struct {
-		Algorithm pkix.AlgorithmIdentifier
-		PublicKey asn1.BitString
-	}
-
-	_, err := asn1.Unmarshal(issuer.RawSubjectPublicKeyInfo, &spki)
-	if err != nil {
-		return "", err
-	}
-	h := hashFunc.New()
-	h.Write(spki.PublicKey.RightAlign())
-	issuerKeyHash := h.Sum(nil)
-
-	h.Reset()
-	h.Write(issuer.RawSubject)
-	issuerNameHash := h.Sum(nil)
-
-	type certID struct {
-		HashAlgorithm  pkix.AlgorithmIdentifier
-		IssuerNameHash []byte
-		IssuerKeyHash  []byte
-		SerialNumber   *big.Int
-	}
-
-	// DER-encode the CertID ASN.1 sequence [RFC6960].
-	certIDBytes, err := asn1.Marshal(certID{
-		HashAlgorithm: pkix.AlgorithmIdentifier{
-			Algorithm: oid,
-		},
-		IssuerNameHash: issuerNameHash,
-		IssuerKeyHash:  issuerKeyHash,
-		SerialNumber:   leaf.SerialNumber,
-	})
-	if err != nil {
-		return "", err
-	}
-
-	// base64url-encode [RFC4648] the bytes of the DER-encoded CertID ASN.1 sequence [RFC6960].
-	encodedBytes := base64.URLEncoding.EncodeToString(certIDBytes)
 
-	// Any trailing '=' characters MUST be stripped.
-	return strings.TrimRight(encodedBytes, "="), nil
+	return fmt.Sprintf("%s.%s",
+		strings.TrimRight(base64.URLEncoding.EncodeToString(leaf.AuthorityKeyId), "="),
+		strings.TrimRight(base64.URLEncoding.EncodeToString(leaf.SerialNumber.Bytes()), "="),
+	), nil
 }
diff --git a/cmd/cmd_renew.go b/cmd/cmd_renew.go
index 70848af6..68bb2bd8 100644
--- a/cmd/cmd_renew.go
+++ b/cmd/cmd_renew.go
@@ -53,11 +53,6 @@ func createRenew() *cli.Command {
 				Name:  "ari-enable",
 				Usage: "Use the renewalInfo endpoint (draft-ietf-acme-ari) to check if a certificate should be renewed.",
 			},
-			&cli.StringFlag{
-				Name:  "ari-hash-name",
-				Value: crypto.SHA256.String(),
-				Usage: "The string representation of the hash expected by the renewalInfo endpoint (e.g. \"SHA-256\").",
-			},
 			&cli.DurationFlag{
 				Name:  "ari-wait-to-renew-duration",
 				Usage: "The maximum duration you're willing to sleep for a renewal time returned by the renewalInfo endpoint.",
@@ -146,11 +141,7 @@ func renewForDomains(ctx *cli.Context, client *lego.Client, certsStorage *Certif
 
 	var ariRenewalTime *time.Time
 	if ctx.Bool("ari-enable") {
-		if len(certificates) < 2 {
-			log.Warnf("[%s] Certificate bundle does not contain issuer, cannot use the renewalInfo endpoint", domain)
-		} else {
-			ariRenewalTime = getARIRenewalTime(ctx, certificates[0], certificates[1], domain, client)
-		}
+		ariRenewalTime = getARIRenewalTime(ctx, cert, domain, client)
 		if ariRenewalTime != nil {
 			now := time.Now().UTC()
 			// Figure out if we need to sleep before renewing.
@@ -216,11 +207,7 @@ func renewForDomains(ctx *cli.Context, client *lego.Client, certsStorage *Certif
 
 	if ariRenewalTime != nil {
 		// Post to the renewalInfo endpoint to indicate that we have renewed and replaced the certificate.
-		err := client.Certificate.UpdateRenewalInfo(certificate.RenewalInfoRequest{
-			Cert:     certificates[0],
-			Issuer:   certificates[1],
-			HashName: ctx.String("ari-hash-name"),
-		})
+		err := client.Certificate.UpdateRenewalInfo(certificate.RenewalInfoRequest{Cert: certificates[0]})
 		if err != nil {
 			log.Warnf("[%s] Failed to update renewal info: %v", domain, err)
 		}
@@ -255,11 +242,7 @@ func renewForCSR(ctx *cli.Context, client *lego.Client, certsStorage *Certificat
 
 	var ariRenewalTime *time.Time
 	if ctx.Bool("ari-enable") {
-		if len(certificates) < 2 {
-			log.Warnf("[%s] Certificate bundle does not contain issuer, cannot use the renewalInfo endpoint", domain)
-		} else {
-			ariRenewalTime = getARIRenewalTime(ctx, certificates[0], certificates[1], domain, client)
-		}
+		ariRenewalTime = getARIRenewalTime(ctx, cert, domain, client)
 		if ariRenewalTime != nil {
 			now := time.Now().UTC()
 			// Figure out if we need to sleep before renewing.
@@ -296,11 +279,7 @@ func renewForCSR(ctx *cli.Context, client *lego.Client, certsStorage *Certificat
 
 	if ariRenewalTime != nil {
 		// Post to the renewalInfo endpoint to indicate that we have renewed and replaced the certificate.
-		err := client.Certificate.UpdateRenewalInfo(certificate.RenewalInfoRequest{
-			Cert:     certificates[0],
-			Issuer:   certificates[1],
-			HashName: ctx.String("ari-hash-name"),
-		})
+		err := client.Certificate.UpdateRenewalInfo(certificate.RenewalInfoRequest{Cert: certificates[0]})
 		if err != nil {
 			log.Warnf("[%s] Failed to update renewal info: %v", domain, err)
 		}
@@ -331,23 +310,19 @@ func needRenewal(x509Cert *x509.Certificate, domain string, days int) bool {
 }
 
 // getARIRenewalTime checks if the certificate needs to be renewed using the renewalInfo endpoint.
-func getARIRenewalTime(ctx *cli.Context, cert, issuer *x509.Certificate, domain string, client *lego.Client) *time.Time {
+func getARIRenewalTime(ctx *cli.Context, cert *x509.Certificate, domain string, client *lego.Client) *time.Time {
 	if cert.IsCA {
 		log.Fatalf("[%s] Certificate bundle starts with a CA certificate", domain)
 	}
 
-	renewalInfo, err := client.Certificate.GetRenewalInfo(certificate.RenewalInfoRequest{
-		Cert:     cert,
-		Issuer:   issuer,
-		HashName: ctx.String("ari-hash-name"),
-	})
+	renewalInfo, err := client.Certificate.GetRenewalInfo(certificate.RenewalInfoRequest{Cert: cert})
 	if err != nil {
 		if errors.Is(err, api.ErrNoARI) {
 			// The server does not advertise a renewal info endpoint.
-			log.Warnf("[%s] acme: %w", domain, err)
+			log.Warnf("[%s] acme: %v", domain, err)
 			return nil
 		}
-		log.Warnf("[%s] acme: calling renewal info endpoint: %w", domain, err)
+		log.Warnf("[%s] acme: calling renewal info endpoint: %v", domain, err)
 		return nil
 	}
 
diff --git a/docs/data/zz_cli_help.toml b/docs/data/zz_cli_help.toml
index b6fd50c0..e3b598b0 100644
--- a/docs/data/zz_cli_help.toml
+++ b/docs/data/zz_cli_help.toml
@@ -82,8 +82,7 @@ USAGE:
 
 OPTIONS:
    --days value                              The number of days left on a certificate to renew it. (default: 0)
-   --ari-enable                              Use the renewalInfo endpoint (draft-ietf-acme-ari) to check if a certificate should be renewed. (default: false)
-   --ari-hash-name value                     The string representation of the hash expected by the renewalInfo endpoint (e.g. "SHA-256").
+   --ari-enable                              Use the renewalInfo endpoint (draft-ietf-acme-ari-02) to check if a certificate should be renewed. (default: false)
    --ari-wait-to-renew-duration value        The maximum duration you're willing to sleep for a renewal time returned by the renewalInfo endpoint. (default: 0s)
    --reuse-key                               Used to indicate you want to reuse your current private key for the new certificate. (default: false)
    --no-bundle                               Do not create a certificate bundle by adding the issuers certificate to the new certificate. (default: false)


Test patch:
diff --git a/certificate/renewal_test.go b/certificate/renewal_test.go
index 5d5e0f25..5f501d63 100644
--- a/certificate/renewal_test.go
+++ b/certificate/renewal_test.go
@@ -1,7 +1,6 @@
 package certificate
 
 import (
-	"crypto"
 	"crypto/rand"
 	"crypto/rsa"
 	"encoding/json"
@@ -40,36 +39,14 @@ TXysJCeyiGnR+KOOjOOQ9ZlO5JUK3OE4hagPLfaIpDDy6RXQt3ss0iNLuB1+IOtp
 HX2RteNJx7YYNeX3Uf960mgo5an6vE8QNAsIoNHYrGyEmXDhTRe9mCHyiW2S7fZq
 o9q12g==
 -----END CERTIFICATE-----`
-	ariIssuerPEM = `-----BEGIN CERTIFICATE-----
-MIIDSzCCAjOgAwIBAgIIOhNWtJ7Igr0wDQYJKoZIhvcNAQELBQAwIDEeMBwGA1UE
-AxMVbWluaWNhIHJvb3QgY2EgM2ExMzU2MCAXDTIyMDMxNzE3NTEwOVoYDzIxMjIw
-MzE3MTc1MTA5WjAgMR4wHAYDVQQDExVtaW5pY2Egcm9vdCBjYSAzYTEzNTYwggEi
-MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDc3P6cxcCZ7FQOQrYuigReSa8T
-IOPNKmlmX9OrTkPwjThiMNEETYKO1ea99yXPK36LUHC6OLmZ9jVQW2Ny1qwQCOy6
-TrquhnwKgtkBMDAZBLySSEXYdKL3r0jA4sflW130/OLwhstU/yv0J8+pj7eSVOR3
-zJBnYd1AqnXHRSwQm299KXgqema7uwsa8cgjrXsBzAhrwrvYlVhpWFSv3lQRDFQg
-c5Z/ZDV9i26qiaJsCCmdisJZWN7N2luUgxdRqzZ4Cr2Xoilg3T+hkb2y/d6ttsPA
-kaSA+pq3q6Qa7/qfGdT5WuUkcHpvKNRWqnwT9rCYlmG00r3hGgc42D/z1VvfAgMB
-AAGjgYYwgYMwDgYDVR0PAQH/BAQDAgKEMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggr
-BgEFBQcDAjASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBQ4zzDRUaXHVKql
-STWkULGU4zGZpTAfBgNVHSMEGDAWgBQ4zzDRUaXHVKqlSTWkULGU4zGZpTANBgkq
-hkiG9w0BAQsFAAOCAQEArbDHhEjGedjb/YjU80aFTPWOMRjgyfQaPPgyxwX6Dsid
-1i2H1x4ud4ntz3sTZZxdQIrOqtlIWTWVCjpStwGxaC+38SdreiTTwy/nikXGa/6W
-ZyQRppR3agh/pl5LHVO6GsJz3YHa7wQhEhj3xsRwa9VrRXgHbLGbPOFVRTHPjaPg
-Gtsv2PN3f67DsPHF47ASqyOIRpLZPQmZIw6D3isJwfl+8CzvlB1veO0Q3uh08IJc
-fspYQXvFBzYa64uKxNAJMi4Pby8cf4r36Wnb7cL4ho3fOHgAltxdW8jgibRzqZpQ
-QKyxn2jX7kxeUDt0hFDJE8lOrhP73m66eBNzxe//FQ==
------END CERTIFICATE-----`
-	ariLeafCertID = "MFswCwYJYIZIAWUDBAIBBCCeWLRusNLb--vmWOkxm34qDjTMWkc3utIhOMoMwKDqbgQg2iiKWySZrD-6c88HMZ6vhIHZPamChLlzGHeZ7pTS8jYCCD6jRWhlRB8c"
+	ariLeafCertID = "OM8w0VGlx1SqpUk1pFCxlOMxmaU.PqNFaGVEHxw"
 )
 
 func Test_makeCertID(t *testing.T) {
 	leaf, err := certcrypto.ParsePEMCertificate([]byte(ariLeafPEM))
 	require.NoError(t, err)
-	issuer, err := certcrypto.ParsePEMCertificate([]byte(ariIssuerPEM))
-	require.NoError(t, err)
 
-	actual, err := makeCertID(leaf, issuer, crypto.SHA256.String())
+	actual, err := makeARICertID(leaf)
 	require.NoError(t, err)
 	assert.Equal(t, ariLeafCertID, actual)
 }
@@ -77,8 +54,6 @@ func Test_makeCertID(t *testing.T) {
 func TestCertifier_GetRenewalInfo(t *testing.T) {
 	leaf, err := certcrypto.ParsePEMCertificate([]byte(ariLeafPEM))
 	require.NoError(t, err)
-	issuer, err := certcrypto.ParsePEMCertificate([]byte(ariIssuerPEM))
-	require.NoError(t, err)
 
 	// Test with a fake API.
 	mux, apiURL := tester.SetupFakeAPI(t)
@@ -109,7 +84,7 @@ func TestCertifier_GetRenewalInfo(t *testing.T) {
 
 	certifier := NewCertifier(core, &resolverMock{}, CertifierOptions{KeyType: certcrypto.RSA2048})
 
-	ri, err := certifier.GetRenewalInfo(RenewalInfoRequest{leaf, issuer, crypto.SHA256.String()})
+	ri, err := certifier.GetRenewalInfo(RenewalInfoRequest{leaf})
 	require.NoError(t, err)
 	require.NotNil(t, ri)
 	assert.Equal(t, "2020-03-17T17:51:09Z", ri.SuggestedWindow.Start.Format(time.RFC3339))
@@ -120,8 +95,6 @@ func TestCertifier_GetRenewalInfo(t *testing.T) {
 func TestCertifier_GetRenewalInfo_errors(t *testing.T) {
 	leaf, err := certcrypto.ParsePEMCertificate([]byte(ariLeafPEM))
 	require.NoError(t, err)
-	issuer, err := certcrypto.ParsePEMCertificate([]byte(ariIssuerPEM))
-	require.NoError(t, err)
 
 	key, err := rsa.GenerateKey(rand.Reader, 2048)
 	require.NoError(t, err, "Could not generate test key")
@@ -135,7 +108,7 @@ func TestCertifier_GetRenewalInfo_errors(t *testing.T) {
 		{
 			desc:       "API timeout",
 			httpClient: &http.Client{Timeout: 500 * time.Millisecond}, // HTTP client that times out after 500ms.
-			request:    RenewalInfoRequest{leaf, issuer, crypto.SHA256.String()},
+			request:    RenewalInfoRequest{leaf},
 			handler: func(w http.ResponseWriter, r *http.Request) {
 				// API that takes 2ms to respond.
 				time.Sleep(2 * time.Millisecond)
@@ -144,20 +117,12 @@ func TestCertifier_GetRenewalInfo_errors(t *testing.T) {
 		{
 			desc:       "API error",
 			httpClient: http.DefaultClient,
-			request:    RenewalInfoRequest{leaf, issuer, crypto.SHA256.String()},
+			request:    RenewalInfoRequest{leaf},
 			handler: func(w http.ResponseWriter, r *http.Request) {
 				// API that responds with error instead of renewal info.
 				http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
 			},
 		},
-		{
-			desc:       "Issuer certificate is nil",
-			httpClient: http.DefaultClient,
-			request:    RenewalInfoRequest{leaf, nil, crypto.SHA256.String()},
-			handler: func(w http.ResponseWriter, r *http.Request) {
-				http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
-			},
-		},
 	}
 
 	for _, test := range testCases {
@@ -183,8 +148,6 @@ func TestCertifier_GetRenewalInfo_errors(t *testing.T) {
 func TestCertifier_UpdateRenewalInfo(t *testing.T) {
 	leaf, err := certcrypto.ParsePEMCertificate([]byte(ariLeafPEM))
 	require.NoError(t, err)
-	issuer, err := certcrypto.ParsePEMCertificate([]byte(ariIssuerPEM))
-	require.NoError(t, err)
 
 	key, err := rsa.GenerateKey(rand.Reader, 2048)
 	require.NoError(t, err, "Could not generate test key")
@@ -217,15 +180,13 @@ func TestCertifier_UpdateRenewalInfo(t *testing.T) {
 
 	certifier := NewCertifier(core, &resolverMock{}, CertifierOptions{KeyType: certcrypto.RSA2048})
 
-	err = certifier.UpdateRenewalInfo(RenewalInfoRequest{leaf, issuer, crypto.SHA256.String()})
+	err = certifier.UpdateRenewalInfo(RenewalInfoRequest{leaf})
 	require.NoError(t, err)
 }
 
 func TestCertifier_UpdateRenewalInfo_errors(t *testing.T) {
 	leaf, err := certcrypto.ParsePEMCertificate([]byte(ariLeafPEM))
 	require.NoError(t, err)
-	issuer, err := certcrypto.ParsePEMCertificate([]byte(ariIssuerPEM))
-	require.NoError(t, err)
 
 	key, err := rsa.GenerateKey(rand.Reader, 2048)
 	require.NoError(t, err, "Could not generate test key")
@@ -236,11 +197,7 @@ func TestCertifier_UpdateRenewalInfo_errors(t *testing.T) {
 	}{
 		{
 			desc:    "API error",
-			request: RenewalInfoRequest{leaf, issuer, crypto.SHA256.String()},
-		},
-		{
-			desc:    "Certificate is nil",
-			request: RenewalInfoRequest{nil, issuer, crypto.SHA256.String()},
+			request: RenewalInfoRequest{leaf},
 		},
 	}