acme: add crypto.SignMessage test coverage

This commit updates the pre-existing TestJWSEncodeJSONCustom test to
also verify JWS signature production works with a crypto.MessageSigner.

Change-Id: I5156cb4da9a7feee98340ff4fb75848da5827055
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/815480
Auto-Submit: Daniel McCarney <daniel@binaryparadox.net>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Carlos Amedee <carlos@golang.org>
diff --git a/acme/jws_test.go b/acme/jws_test.go
index d5f00ba..906ca18 100644
--- a/acme/jws_test.go
+++ b/acme/jws_test.go
@@ -14,6 +14,7 @@
 	"encoding/base64"
 	"encoding/json"
 	"encoding/pem"
+	"errors"
 	"fmt"
 	"io"
 	"math/big"
@@ -353,6 +354,22 @@
 	return s.sig, nil
 }
 
+type customTestMessageSigner struct {
+	customTestSigner
+	msg  []byte
+	opts crypto.SignerOpts
+}
+
+func (s *customTestMessageSigner) Sign(io.Reader, []byte, crypto.SignerOpts) ([]byte, error) {
+	return nil, errors.New("customTestSigner: Sign() called instead of SignMessage()")
+}
+
+func (s *customTestMessageSigner) SignMessage(_ io.Reader, msg []byte, opts crypto.SignerOpts) ([]byte, error) {
+	s.msg = msg
+	s.opts = opts
+	return s.sig, nil
+}
+
 func TestJWSEncodeJSONCustom(t *testing.T) {
 	claims := struct{ Msg string }{"hello"}
 	const (
@@ -391,24 +408,33 @@
 	)
 
 	tt := []struct {
-		alg, phead    string
+		name, phead   string
 		pub           crypto.PublicKey
 		stdsig, jwsig string
+		msgSigner     bool
 	}{
-		{"ES256", es256phead, testKeyEC.Public(), es256stdsig, es256jwsig},
-		{"RS256", rs256phead, testKey.Public(), testsig, testsig},
+		{"ES256", es256phead, testKeyEC.Public(), es256stdsig, es256jwsig, false},
+		{"RS256", rs256phead, testKey.Public(), testsig, testsig, false},
+		{"ES256-MessageSigner", es256phead, testKeyEC.Public(), es256stdsig, es256jwsig, true},
+		{"RS256-MessageSigner", rs256phead, testKey.Public(), testsig, testsig, true},
 	}
 	for _, tc := range tt {
 		tc := tc
-		t.Run(tc.alg, func(t *testing.T) {
+		t.Run(tc.name, func(t *testing.T) {
 			stdsig, err := base64.RawStdEncoding.DecodeString(tc.stdsig)
 			if err != nil {
 				t.Errorf("couldn't decode test vector: %v", err)
 			}
-			signer := &customTestSigner{
+			cs := customTestSigner{
 				sig: stdsig,
 				pub: tc.pub,
 			}
+			var signer crypto.Signer = &cs
+			var ms *customTestMessageSigner
+			if tc.msgSigner {
+				ms = &customTestMessageSigner{customTestSigner: cs}
+				signer = ms
+			}
 
 			b, err := jwsEncodeJSON(claims, signer, noKeyID, "nonce", "url")
 			if err != nil {
@@ -427,6 +453,14 @@
 			if j.Sig != tc.jwsig {
 				t.Errorf("j.Sig = %q\nwant %q", j.Sig, tc.jwsig)
 			}
+			if ms != nil {
+				if want := tc.phead + "." + payload; string(ms.msg) != want {
+					t.Errorf("msg = %q; want %q", ms.msg, want)
+				}
+				if ms.opts != crypto.SHA256 {
+					t.Errorf("opts = %v; want %v", ms.opts, crypto.SHA256)
+				}
+			}
 		})
 	}
 }