From e448e81dc4f62009e51e597fbe9cdd62ceb09b19 Mon Sep 17 00:00:00 2001 From: Daniel McCarney Date: Wed, 30 Oct 2019 13:59:41 -0400 Subject: [PATCH] deps: update square/go-jose to v2.4.0 (#4518) This branch also updates the WFE2 parseJWS function to match the error string fixed in the upstream project for the case where a JWS EC public key fails to unmarshal due to an incorrect length. Resolves #4300 --- go.mod | 2 +- go.sum | 2 + vendor/gopkg.in/square/go-jose.v2/.travis.yml | 6 +- .../gopkg.in/square/go-jose.v2/asymmetric.go | 4 +- .../square/go-jose.v2/cipher/ecdh_es.go | 28 +++++- vendor/gopkg.in/square/go-jose.v2/crypter.go | 14 ++- vendor/gopkg.in/square/go-jose.v2/jwk.go | 4 +- vendor/gopkg.in/square/go-jose.v2/jws.go | 95 ++++++++++++++----- vendor/gopkg.in/square/go-jose.v2/opaque.go | 61 ++++++++++++ vendor/gopkg.in/square/go-jose.v2/shared.go | 21 ++++ vendor/gopkg.in/square/go-jose.v2/signing.go | 66 ++++++++++--- vendor/modules.txt | 2 +- wfe2/verify.go | 7 +- 13 files changed, 254 insertions(+), 58 deletions(-) diff --git a/go.mod b/go.mod index ac05cbdc3..e06d8b79c 100644 --- a/go.mod +++ b/go.mod @@ -46,6 +46,6 @@ require ( google.golang.org/genproto v0.0.0-20190415143225-d1146b9035b9 // indirect google.golang.org/grpc v1.20.0 gopkg.in/go-gorp/gorp.v2 v2.0.0-20180410155428-6032c66e0f5f - gopkg.in/square/go-jose.v2 v2.3.1 + gopkg.in/square/go-jose.v2 v2.4.0 gopkg.in/yaml.v2 v2.2.2 ) diff --git a/go.sum b/go.sum index 5c0d9f7d2..419570518 100644 --- a/go.sum +++ b/go.sum @@ -165,6 +165,8 @@ gopkg.in/go-gorp/gorp.v2 v2.0.0-20180410155428-6032c66e0f5f h1:zundYZrPliLrlQV98 gopkg.in/go-gorp/gorp.v2 v2.0.0-20180410155428-6032c66e0f5f/go.mod h1:eJwu1bWCXesk9aw26U78PFtctx3Y8haXGmL7x3VJlrw= gopkg.in/square/go-jose.v2 v2.3.1 h1:SK5KegNXmKmqE342YYN2qPHEnUYeoMiXXl1poUlI+o4= gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/square/go-jose.v2 v2.4.0 h1:0kXPskUMGAXXWJlP05ktEMOV0vmzFQUWw6d+aZJQU8A= +gopkg.in/square/go-jose.v2 v2.4.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/vendor/gopkg.in/square/go-jose.v2/.travis.yml b/vendor/gopkg.in/square/go-jose.v2/.travis.yml index fc501ca9b..9ab2abf6f 100644 --- a/vendor/gopkg.in/square/go-jose.v2/.travis.yml +++ b/vendor/gopkg.in/square/go-jose.v2/.travis.yml @@ -8,11 +8,9 @@ matrix: - go: tip go: -- '1.7.x' -- '1.8.x' -- '1.9.x' -- '1.10.x' - '1.11.x' +- '1.12.x' +- tip go_import_path: gopkg.in/square/go-jose.v2 diff --git a/vendor/gopkg.in/square/go-jose.v2/asymmetric.go b/vendor/gopkg.in/square/go-jose.v2/asymmetric.go index 67935561b..b69aa0369 100644 --- a/vendor/gopkg.in/square/go-jose.v2/asymmetric.go +++ b/vendor/gopkg.in/square/go-jose.v2/asymmetric.go @@ -29,7 +29,7 @@ import ( "math/big" "golang.org/x/crypto/ed25519" - "gopkg.in/square/go-jose.v2/cipher" + josecipher "gopkg.in/square/go-jose.v2/cipher" "gopkg.in/square/go-jose.v2/json" ) @@ -288,7 +288,7 @@ func (ctx rsaDecrypterSigner) signPayload(payload []byte, alg SignatureAlgorithm out, err = rsa.SignPKCS1v15(RandReader, ctx.privateKey, hash, hashed) case PS256, PS384, PS512: out, err = rsa.SignPSS(RandReader, ctx.privateKey, hash, hashed, &rsa.PSSOptions{ - SaltLength: rsa.PSSSaltLengthAuto, + SaltLength: rsa.PSSSaltLengthEqualsHash, }) } diff --git a/vendor/gopkg.in/square/go-jose.v2/cipher/ecdh_es.go b/vendor/gopkg.in/square/go-jose.v2/cipher/ecdh_es.go index c128e327f..093c64674 100644 --- a/vendor/gopkg.in/square/go-jose.v2/cipher/ecdh_es.go +++ b/vendor/gopkg.in/square/go-jose.v2/cipher/ecdh_es.go @@ -17,8 +17,10 @@ package josecipher import ( + "bytes" "crypto" "crypto/ecdsa" + "crypto/elliptic" "encoding/binary" ) @@ -44,16 +46,38 @@ func DeriveECDHES(alg string, apuData, apvData []byte, priv *ecdsa.PrivateKey, p panic("public key not on same curve as private key") } - z, _ := priv.PublicKey.Curve.ScalarMult(pub.X, pub.Y, priv.D.Bytes()) - reader := NewConcatKDF(crypto.SHA256, z.Bytes(), algID, ptyUInfo, ptyVInfo, supPubInfo, []byte{}) + z, _ := priv.Curve.ScalarMult(pub.X, pub.Y, priv.D.Bytes()) + zBytes := z.Bytes() + // Note that calling z.Bytes() on a big.Int may strip leading zero bytes from + // the returned byte array. This can lead to a problem where zBytes will be + // shorter than expected which breaks the key derivation. Therefore we must pad + // to the full length of the expected coordinate here before calling the KDF. + octSize := dSize(priv.Curve) + if len(zBytes) != octSize { + zBytes = append(bytes.Repeat([]byte{0}, octSize-len(zBytes)), zBytes...) + } + + reader := NewConcatKDF(crypto.SHA256, zBytes, algID, ptyUInfo, ptyVInfo, supPubInfo, []byte{}) key := make([]byte, size) // Read on the KDF will never fail _, _ = reader.Read(key) + return key } +// dSize returns the size in octets for a coordinate on a elliptic curve. +func dSize(curve elliptic.Curve) int { + order := curve.Params().P + bitLen := order.BitLen() + size := bitLen / 8 + if bitLen%8 != 0 { + size++ + } + return size +} + func lengthPrefixed(data []byte) []byte { out := make([]byte, len(data)+4) binary.BigEndian.PutUint32(out, uint32(len(data))) diff --git a/vendor/gopkg.in/square/go-jose.v2/crypter.go b/vendor/gopkg.in/square/go-jose.v2/crypter.go index c45c71206..d24cabf6b 100644 --- a/vendor/gopkg.in/square/go-jose.v2/crypter.go +++ b/vendor/gopkg.in/square/go-jose.v2/crypter.go @@ -141,6 +141,8 @@ func NewEncrypter(enc ContentEncryption, rcpt Recipient, opts *EncrypterOptions) keyID, rawKey = encryptionKey.KeyID, encryptionKey.Key case *JSONWebKey: keyID, rawKey = encryptionKey.KeyID, encryptionKey.Key + case OpaqueKeyEncrypter: + keyID, rawKey = encryptionKey.KeyID(), encryptionKey default: rawKey = encryptionKey } @@ -267,9 +269,11 @@ func makeJWERecipient(alg KeyAlgorithm, encryptionKey interface{}) (recipientKey recipient, err := makeJWERecipient(alg, encryptionKey.Key) recipient.keyID = encryptionKey.KeyID return recipient, err - default: - return recipientKeyInfo{}, ErrUnsupportedKeyType } + if encrypter, ok := encryptionKey.(OpaqueKeyEncrypter); ok { + return newOpaqueKeyEncrypter(alg, encrypter) + } + return recipientKeyInfo{}, ErrUnsupportedKeyType } // newDecrypter creates an appropriate decrypter based on the key type @@ -295,9 +299,11 @@ func newDecrypter(decryptionKey interface{}) (keyDecrypter, error) { return newDecrypter(decryptionKey.Key) case *JSONWebKey: return newDecrypter(decryptionKey.Key) - default: - return nil, ErrUnsupportedKeyType } + if okd, ok := decryptionKey.(OpaqueKeyDecrypter); ok { + return &opaqueKeyDecrypter{decrypter: okd}, nil + } + return nil, ErrUnsupportedKeyType } // Implementation of encrypt method producing a JWE object. diff --git a/vendor/gopkg.in/square/go-jose.v2/jwk.go b/vendor/gopkg.in/square/go-jose.v2/jwk.go index 6cb8adb84..936a02021 100644 --- a/vendor/gopkg.in/square/go-jose.v2/jwk.go +++ b/vendor/gopkg.in/square/go-jose.v2/jwk.go @@ -357,11 +357,11 @@ func (key rawJSONWebKey) ecPublicKey() (*ecdsa.PublicKey, error) { // the curve specified in the "crv" parameter. // https://tools.ietf.org/html/rfc7518#section-6.2.1.2 if curveSize(curve) != len(key.X.data) { - return nil, fmt.Errorf("square/go-jose: invalid EC private key, wrong length for x") + return nil, fmt.Errorf("square/go-jose: invalid EC public key, wrong length for x") } if curveSize(curve) != len(key.Y.data) { - return nil, fmt.Errorf("square/go-jose: invalid EC private key, wrong length for y") + return nil, fmt.Errorf("square/go-jose: invalid EC public key, wrong length for y") } x := key.X.bigInt() diff --git a/vendor/gopkg.in/square/go-jose.v2/jws.go b/vendor/gopkg.in/square/go-jose.v2/jws.go index 8b59b6ab2..e52a47662 100644 --- a/vendor/gopkg.in/square/go-jose.v2/jws.go +++ b/vendor/gopkg.in/square/go-jose.v2/jws.go @@ -17,6 +17,7 @@ package jose import ( + "bytes" "encoding/base64" "errors" "fmt" @@ -75,13 +76,21 @@ type Signature struct { } // ParseSigned parses a signed message in compact or full serialization format. -func ParseSigned(input string) (*JSONWebSignature, error) { - input = stripWhitespace(input) - if strings.HasPrefix(input, "{") { - return parseSignedFull(input) +func ParseSigned(signature string) (*JSONWebSignature, error) { + signature = stripWhitespace(signature) + if strings.HasPrefix(signature, "{") { + return parseSignedFull(signature) } - return parseSignedCompact(input) + return parseSignedCompact(signature, nil) +} + +// ParseDetached parses a signed message in compact serialization format with detached payload. +func ParseDetached(signature string, payload []byte) (*JSONWebSignature, error) { + if payload == nil { + return nil, errors.New("square/go-jose: nil payload") + } + return parseSignedCompact(stripWhitespace(signature), payload) } // Get a header value @@ -94,19 +103,38 @@ func (sig Signature) mergedHeaders() rawHeader { // Compute data to be signed func (obj JSONWebSignature) computeAuthData(payload []byte, signature *Signature) []byte { - var serializedProtected string + var authData bytes.Buffer + + protectedHeader := new(rawHeader) if signature.original != nil && signature.original.Protected != nil { - serializedProtected = signature.original.Protected.base64() + if err := json.Unmarshal(signature.original.Protected.bytes(), protectedHeader); err != nil { + panic(err) + } + authData.WriteString(signature.original.Protected.base64()) } else if signature.protected != nil { - serializedProtected = base64.RawURLEncoding.EncodeToString(mustSerializeJSON(signature.protected)) - } else { - serializedProtected = "" + protectedHeader = signature.protected + authData.WriteString(base64.RawURLEncoding.EncodeToString(mustSerializeJSON(protectedHeader))) } - return []byte(fmt.Sprintf("%s.%s", - serializedProtected, - base64.RawURLEncoding.EncodeToString(payload))) + needsBase64 := true + + if protectedHeader != nil { + var err error + if needsBase64, err = protectedHeader.getB64(); err != nil { + needsBase64 = true + } + } + + authData.WriteByte('.') + + if needsBase64 { + authData.WriteString(base64.RawURLEncoding.EncodeToString(payload)) + } else { + authData.Write(payload) + } + + return authData.Bytes() } // parseSignedFull parses a message in full format. @@ -246,20 +274,26 @@ func (parsed *rawJSONWebSignature) sanitized() (*JSONWebSignature, error) { } // parseSignedCompact parses a message in compact format. -func parseSignedCompact(input string) (*JSONWebSignature, error) { +func parseSignedCompact(input string, payload []byte) (*JSONWebSignature, error) { parts := strings.Split(input, ".") if len(parts) != 3 { return nil, fmt.Errorf("square/go-jose: compact JWS format must have three parts") } + if parts[1] != "" && payload != nil { + return nil, fmt.Errorf("square/go-jose: payload is not detached") + } + rawProtected, err := base64.RawURLEncoding.DecodeString(parts[0]) if err != nil { return nil, err } - payload, err := base64.RawURLEncoding.DecodeString(parts[1]) - if err != nil { - return nil, err + if payload == nil { + payload, err = base64.RawURLEncoding.DecodeString(parts[1]) + if err != nil { + return nil, err + } } signature, err := base64.RawURLEncoding.DecodeString(parts[2]) @@ -275,19 +309,30 @@ func parseSignedCompact(input string) (*JSONWebSignature, error) { return raw.sanitized() } -// CompactSerialize serializes an object using the compact serialization format. -func (obj JSONWebSignature) CompactSerialize() (string, error) { +func (obj JSONWebSignature) compactSerialize(detached bool) (string, error) { if len(obj.Signatures) != 1 || obj.Signatures[0].header != nil || obj.Signatures[0].protected == nil { return "", ErrNotSupported } - serializedProtected := mustSerializeJSON(obj.Signatures[0].protected) + serializedProtected := base64.RawURLEncoding.EncodeToString(mustSerializeJSON(obj.Signatures[0].protected)) + payload := "" + signature := base64.RawURLEncoding.EncodeToString(obj.Signatures[0].Signature) - return fmt.Sprintf( - "%s.%s.%s", - base64.RawURLEncoding.EncodeToString(serializedProtected), - base64.RawURLEncoding.EncodeToString(obj.payload), - base64.RawURLEncoding.EncodeToString(obj.Signatures[0].Signature)), nil + if !detached { + payload = base64.RawURLEncoding.EncodeToString(obj.payload) + } + + return fmt.Sprintf("%s.%s.%s", serializedProtected, payload, signature), nil +} + +// CompactSerialize serializes an object using the compact serialization format. +func (obj JSONWebSignature) CompactSerialize() (string, error) { + return obj.compactSerialize(false) +} + +// DetachedCompactSerialize serializes an object using the compact serialization format with detached payload. +func (obj JSONWebSignature) DetachedCompactSerialize() (string, error) { + return obj.compactSerialize(true) } // FullSerialize serializes an object using the full JSON serialization format. diff --git a/vendor/gopkg.in/square/go-jose.v2/opaque.go b/vendor/gopkg.in/square/go-jose.v2/opaque.go index 4a8bd8f32..df747f992 100644 --- a/vendor/gopkg.in/square/go-jose.v2/opaque.go +++ b/vendor/gopkg.in/square/go-jose.v2/opaque.go @@ -81,3 +81,64 @@ type opaqueVerifier struct { func (o *opaqueVerifier) verifyPayload(payload []byte, signature []byte, alg SignatureAlgorithm) error { return o.verifier.VerifyPayload(payload, signature, alg) } + +// OpaqueKeyEncrypter is an interface that supports encrypting keys with an opaque key. +type OpaqueKeyEncrypter interface { + // KeyID returns the kid + KeyID() string + // Algs returns a list of supported key encryption algorithms. + Algs() []KeyAlgorithm + // encryptKey encrypts the CEK using the given algorithm. + encryptKey(cek []byte, alg KeyAlgorithm) (recipientInfo, error) +} + +type opaqueKeyEncrypter struct { + encrypter OpaqueKeyEncrypter +} + +func newOpaqueKeyEncrypter(alg KeyAlgorithm, encrypter OpaqueKeyEncrypter) (recipientKeyInfo, error) { + var algSupported bool + for _, salg := range encrypter.Algs() { + if alg == salg { + algSupported = true + break + } + } + if !algSupported { + return recipientKeyInfo{}, ErrUnsupportedAlgorithm + } + + return recipientKeyInfo{ + keyID: encrypter.KeyID(), + keyAlg: alg, + keyEncrypter: &opaqueKeyEncrypter{ + encrypter: encrypter, + }, + }, nil +} + +func (oke *opaqueKeyEncrypter) encryptKey(cek []byte, alg KeyAlgorithm) (recipientInfo, error) { + return oke.encrypter.encryptKey(cek, alg) +} + +//OpaqueKeyDecrypter is an interface that supports decrypting keys with an opaque key. +type OpaqueKeyDecrypter interface { + DecryptKey(encryptedKey []byte, header Header) ([]byte, error) +} + +type opaqueKeyDecrypter struct { + decrypter OpaqueKeyDecrypter +} + +func (okd *opaqueKeyDecrypter) decryptKey(headers rawHeader, recipient *recipientInfo, generator keyGenerator) ([]byte, error) { + mergedHeaders := rawHeader{} + mergedHeaders.merge(&headers) + mergedHeaders.merge(recipient.header) + + header, err := mergedHeaders.sanitized() + if err != nil { + return nil, err + } + + return okd.decrypter.DecryptKey(recipient.encryptedKey, header) +} diff --git a/vendor/gopkg.in/square/go-jose.v2/shared.go b/vendor/gopkg.in/square/go-jose.v2/shared.go index b0a6255ec..f8438641f 100644 --- a/vendor/gopkg.in/square/go-jose.v2/shared.go +++ b/vendor/gopkg.in/square/go-jose.v2/shared.go @@ -153,12 +153,18 @@ const ( headerJWK = "jwk" // *JSONWebKey headerKeyID = "kid" // string headerNonce = "nonce" // string + headerB64 = "b64" // bool headerP2C = "p2c" // *byteBuffer (int) headerP2S = "p2s" // *byteBuffer ([]byte) ) +// supportedCritical is the set of supported extensions that are understood and processed. +var supportedCritical = map[string]bool{ + headerB64: true, +} + // rawHeader represents the JOSE header for JWE/JWS objects (used for parsing). // // The decoding of the constituent items is deferred because we want to marshal @@ -349,6 +355,21 @@ func (parsed rawHeader) getP2S() (*byteBuffer, error) { return parsed.getByteBuffer(headerP2S) } +// getB64 extracts parsed "b64" from the raw JSON, defaulting to true. +func (parsed rawHeader) getB64() (bool, error) { + v := parsed[headerB64] + if v == nil { + return true, nil + } + + var b64 bool + err := json.Unmarshal(*v, &b64) + if err != nil { + return true, err + } + return b64, nil +} + // sanitized produces a cleaned-up header object from the raw JSON. func (parsed rawHeader) sanitized() (h Header, err error) { for k, v := range parsed { diff --git a/vendor/gopkg.in/square/go-jose.v2/signing.go b/vendor/gopkg.in/square/go-jose.v2/signing.go index be6cf0481..664a51cc4 100644 --- a/vendor/gopkg.in/square/go-jose.v2/signing.go +++ b/vendor/gopkg.in/square/go-jose.v2/signing.go @@ -17,6 +17,7 @@ package jose import ( + "bytes" "crypto/ecdsa" "crypto/rsa" "encoding/base64" @@ -77,6 +78,27 @@ func (so *SignerOptions) WithType(typ ContentType) *SignerOptions { return so.WithHeader(HeaderType, typ) } +// WithCritical adds the given names to the critical ("crit") header and returns +// the updated SignerOptions. +func (so *SignerOptions) WithCritical(names ...string) *SignerOptions { + if so.ExtraHeaders[headerCritical] == nil { + so.WithHeader(headerCritical, make([]string, 0, len(names))) + } + crit := so.ExtraHeaders[headerCritical].([]string) + so.ExtraHeaders[headerCritical] = append(crit, names...) + return so +} + +// WithBase64 adds a base64url-encode payload ("b64") header and returns the updated +// SignerOptions. When the "b64" value is "false", the payload is not base64 encoded. +func (so *SignerOptions) WithBase64(b64 bool) *SignerOptions { + if !b64 { + so.WithHeader(headerB64, b64) + so.WithCritical(headerB64) + } + return so +} + type payloadSigner interface { signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error) } @@ -233,7 +255,10 @@ func (ctx *genericSigner) Sign(payload []byte) (*JSONWebSignature, error) { if ctx.embedJWK { protected[headerJWK] = recipient.publicKey() } else { - protected[headerKeyID] = recipient.publicKey().KeyID + keyID := recipient.publicKey().KeyID + if keyID != "" { + protected[headerKeyID] = keyID + } } } @@ -250,12 +275,26 @@ func (ctx *genericSigner) Sign(payload []byte) (*JSONWebSignature, error) { } serializedProtected := mustSerializeJSON(protected) + needsBase64 := true - input := []byte(fmt.Sprintf("%s.%s", - base64.RawURLEncoding.EncodeToString(serializedProtected), - base64.RawURLEncoding.EncodeToString(payload))) + if b64, ok := protected[headerB64]; ok { + if needsBase64, ok = b64.(bool); !ok { + return nil, errors.New("square/go-jose: Invalid b64 header parameter") + } + } - signatureInfo, err := recipient.signer.signPayload(input, recipient.sigAlg) + var input bytes.Buffer + + input.WriteString(base64.RawURLEncoding.EncodeToString(serializedProtected)) + input.WriteByte('.') + + if needsBase64 { + input.WriteString(base64.RawURLEncoding.EncodeToString(payload)) + } else { + input.Write(payload) + } + + signatureInfo, err := recipient.signer.signPayload(input.Bytes(), recipient.sigAlg) if err != nil { return nil, err } @@ -324,9 +363,11 @@ func (obj JSONWebSignature) DetachedVerify(payload []byte, verificationKey inter if err != nil { return err } - if len(critical) > 0 { - // Unsupported crit header - return ErrCryptoFailure + + for _, name := range critical { + if !supportedCritical[name] { + return ErrCryptoFailure + } } input := obj.computeAuthData(payload, &signature) @@ -366,15 +407,18 @@ func (obj JSONWebSignature) DetachedVerifyMulti(payload []byte, verificationKey return -1, Signature{}, err } +outer: for i, signature := range obj.Signatures { headers := signature.mergedHeaders() critical, err := headers.getCritical() if err != nil { continue } - if len(critical) > 0 { - // Unsupported crit header - continue + + for _, name := range critical { + if !supportedCritical[name] { + continue outer + } } input := obj.computeAuthData(payload, &signature) diff --git a/vendor/modules.txt b/vendor/modules.txt index 333a0b85f..0091cfa5d 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -167,7 +167,7 @@ google.golang.org/grpc/tap gopkg.in/fsnotify.v1 # gopkg.in/go-gorp/gorp.v2 v2.0.0-20180410155428-6032c66e0f5f gopkg.in/go-gorp/gorp.v2 -# gopkg.in/square/go-jose.v2 v2.3.1 +# gopkg.in/square/go-jose.v2 v2.4.0 gopkg.in/square/go-jose.v2 gopkg.in/square/go-jose.v2/cipher gopkg.in/square/go-jose.v2/json diff --git a/wfe2/verify.go b/wfe2/verify.go index 2ca4cedda..b6d1a38f3 100644 --- a/wfe2/verify.go +++ b/wfe2/verify.go @@ -315,12 +315,7 @@ func (wfe *WebFrontEndImpl) parseJWS(body []byte) (*jose.JSONWebSignature, *prob parsedJWS, err := jose.ParseSigned(bodyStr) if err != nil { wfe.stats.joseErrorCount.With(prometheus.Labels{"type": "JWSParseError"}).Inc() - // TODO(#4300): This error references private keys, while the issue is - // actually with public keys. A fix has been merged upstream but we - // are waiting until a tagged release containing the change is made. - // Once there is a release containing the fix we'll need to update - // the dep and fix this check. - if strings.HasPrefix(err.Error(), "failed to unmarshal JWK: square/go-jose: invalid EC private key, wrong length") { + if strings.HasPrefix(err.Error(), "failed to unmarshal JWK: square/go-jose: invalid EC public key, wrong length") { return nil, probs.Malformed("Parse error reading JWS: EC public key has incorrect padding") } return nil, probs.Malformed("Parse error reading JWS")