acme: expose Client KID field

Expose the previously private KID field of the Client type. This allows
callers which have locally cached their key identity to avoid needing
to make a call to the ACME service every time they construct a new
client.

Fixes golang/go#46303

Change-Id: I219167c5b941f56a2028c4bc253ff56386845549
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/354697
Trust: Katie Hockman <katie@golang.org>
Reviewed-by: Katie Hockman <katie@golang.org>
Trust: Roland Shoemaker <roland@golang.org>
Run-TryBot: Roland Shoemaker <roland@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
diff --git a/acme/acme.go b/acme/acme.go
index 73b19ef..271df26 100644
--- a/acme/acme.go
+++ b/acme/acme.go
@@ -125,7 +125,9 @@
 
 	cacheMu sync.Mutex
 	dir     *Directory // cached result of Client's Discover method
-	kid     keyID      // cached Account.URI obtained from registerRFC or getAccountRFC
+	// KID is the key identifier provided by the CA. If not provided it will be
+	// retrieved from the CA by making a call to the registration endpoint.
+	KID KeyID
 
 	noncesMu sync.Mutex
 	nonces   map[string]struct{} // nonces collected from previous responses
@@ -140,21 +142,21 @@
 //
 // When in pre-RFC mode or when c.getRegRFC responds with an error, accountKID
 // returns noKeyID.
-func (c *Client) accountKID(ctx context.Context) keyID {
+func (c *Client) accountKID(ctx context.Context) KeyID {
 	c.cacheMu.Lock()
 	defer c.cacheMu.Unlock()
 	if !c.dir.rfcCompliant() {
 		return noKeyID
 	}
-	if c.kid != noKeyID {
-		return c.kid
+	if c.KID != noKeyID {
+		return c.KID
 	}
 	a, err := c.getRegRFC(ctx)
 	if err != nil {
 		return noKeyID
 	}
-	c.kid = keyID(a.URI)
-	return c.kid
+	c.KID = KeyID(a.URI)
+	return c.KID
 }
 
 // Discover performs ACME server discovery using c.DirectoryURL.
diff --git a/acme/jws.go b/acme/jws.go
index 8c3ecce..8a097da 100644
--- a/acme/jws.go
+++ b/acme/jws.go
@@ -20,12 +20,12 @@
 	"math/big"
 )
 
-// keyID is the account identity provided by a CA during registration.
-type keyID string
+// KeyID is the account key identity provided by a CA during registration.
+type KeyID string
 
 // noKeyID indicates that jwsEncodeJSON should compute and use JWK instead of a KID.
 // See jwsEncodeJSON for details.
-const noKeyID = keyID("")
+const noKeyID = KeyID("")
 
 // noPayload indicates jwsEncodeJSON will encode zero-length octet string
 // in a JWS request. This is called POST-as-GET in RFC 8555 and is used to make
@@ -43,14 +43,14 @@
 
 // jwsEncodeJSON signs claimset using provided key and a nonce.
 // The result is serialized in JSON format containing either kid or jwk
-// fields based on the provided keyID value.
+// fields based on the provided KeyID value.
 //
 // If kid is non-empty, its quoted value is inserted in the protected head
 // as "kid" field value. Otherwise, JWK is computed using jwkEncode and inserted
 // as "jwk" field value. The "jwk" and "kid" fields are mutually exclusive.
 //
 // See https://tools.ietf.org/html/rfc7515#section-7.
-func jwsEncodeJSON(claimset interface{}, key crypto.Signer, kid keyID, nonce, url string) ([]byte, error) {
+func jwsEncodeJSON(claimset interface{}, key crypto.Signer, kid KeyID, nonce, url string) ([]byte, error) {
 	alg, sha := jwsHasher(key.Public())
 	if alg == "" || !sha.Available() {
 		return nil, ErrUnsupportedKey
diff --git a/acme/jws_test.go b/acme/jws_test.go
index c8a1e8b..738f1ef 100644
--- a/acme/jws_test.go
+++ b/acme/jws_test.go
@@ -196,7 +196,7 @@
 }
 
 func TestJWSEncodeKID(t *testing.T) {
-	kid := keyID("https://example.org/account/1")
+	kid := KeyID("https://example.org/account/1")
 	claims := struct{ Msg string }{"Hello JWS"}
 	// JWS signed with testKeyEC
 	const (
diff --git a/acme/rfc8555.go b/acme/rfc8555.go
index f9d3011..928a5aa 100644
--- a/acme/rfc8555.go
+++ b/acme/rfc8555.go
@@ -78,7 +78,7 @@
 	}
 	// Cache Account URL even if we return an error to the caller.
 	// It is by all means a valid and usable "kid" value for future requests.
-	c.kid = keyID(a.URI)
+	c.KID = KeyID(a.URI)
 	if res.StatusCode == http.StatusOK {
 		return nil, ErrAccountAlreadyExists
 	}
diff --git a/acme/rfc8555_test.go b/acme/rfc8555_test.go
index 07e2f29..4882759 100644
--- a/acme/rfc8555_test.go
+++ b/acme/rfc8555_test.go
@@ -344,7 +344,7 @@
 	if !didPrompt {
 		t.Error("tos prompt wasn't called")
 	}
-	if v := cl.accountKID(ctx); v != keyID(okAccount.URI) {
+	if v := cl.accountKID(ctx); v != KeyID(okAccount.URI) {
 		t.Errorf("account kid = %q; want %q", v, okAccount.URI)
 	}
 }
@@ -482,7 +482,7 @@
 	if !didPrompt {
 		t.Error("tos prompt wasn't called")
 	}
-	if v := cl.accountKID(ctx); v != keyID(okAccount.URI) {
+	if v := cl.accountKID(ctx); v != KeyID(okAccount.URI) {
 		t.Errorf("account kid = %q; want %q", v, okAccount.URI)
 	}
 }
@@ -502,7 +502,7 @@
 	if err != ErrAccountAlreadyExists {
 		t.Errorf("err = %v; want %v", err, ErrAccountAlreadyExists)
 	}
-	kid := keyID(s.url("/accounts/1"))
+	kid := KeyID(s.url("/accounts/1"))
 	if v := cl.accountKID(context.Background()); v != kid {
 		t.Errorf("account kid = %q; want %q", v, kid)
 	}