wfe: Separately handle badSignature at JWS parse time (#8091)

solve https://github.com/letsencrypt/boulder/issues/8088

RFC8555 6.2 requires badSignatureAlgorithm on unacceptable JWS signing
algorithm, but current boulder return malform:failed to parse jws error
instead

Its because this only checks about JWS protected header's signature
algorithm, current checkAlgorithm is while too late to catch parse time
error but not redundant, as it checks against a key and signed message

---------

Co-authored-by: Samantha Frank <hello@entropy.cat>
This commit is contained in:
orangepizza 2025-04-09 07:45:06 +09:00 committed by GitHub
parent ff9e59d70b
commit 5cc8a77ce3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 24 additions and 0 deletions

View File

@ -369,6 +369,16 @@ func (wfe *WebFrontEndImpl) parseJWS(body []byte) (*bJSONWebSignature, error) {
bodyStr := string(body)
parsedJWS, err := jose.ParseSigned(bodyStr, getSupportedAlgs())
if err != nil {
var unexpectedSignAlgoErr *jose.ErrUnexpectedSignatureAlgorithm
if errors.As(err, &unexpectedSignAlgoErr) {
wfe.stats.joseErrorCount.With(prometheus.Labels{"type": "JWSAlgorithmCheckFailed"}).Inc()
return nil, berrors.BadSignatureAlgorithmError(
"JWS signature header contains unsupported algorithm %q, expected one of %s",
unexpectedSignAlgoErr.Got,
getSupportedAlgs(),
)
}
wfe.stats.joseErrorCount.With(prometheus.Labels{"type": "JWSParseError"}).Inc()
return nil, berrors.MalformedError("Parse error reading JWS")
}

View File

@ -972,6 +972,13 @@ func TestParseJWSRequest(t *testing.T) {
"payload": "Zm9v",
"signatures": ["PKWWclRsiHF4bm-nmpxDez6Y_3Mdtu263YeYklbGYt1EiMOLiKY_dr_EqhUUKAKEWysFLO-hQLXVU7kVkHeYWQFFOA18oFgcZgkSF2Pr3DNZrVj9e2gl0eZ2i2jk6X5GYPt1lIfok_DrL92wrxEKGcrmxqXXGm0JgP6Al2VGapKZK2HaYbCHoGvtzNmzUX9rC21sKewq5CquJRvTmvQp5bmU7Q9KeafGibFr0jl6IA3W5LBGgf6xftuUtEVEbKmKaKtaG7tXsQH1mIVOPUZZoLWz9sWJSFLmV0QSXm3ZHV0DrOhLfcADbOCoQBMeGdseBQZuUO541A3BEKGv2Aikjw"]
}
`
wrongSignatureTypeJWSBody := `
{
"protected": "eyJhbGciOiJIUzI1NiJ9",
"payload" : "IiI",
"signature" : "5WiUupHzCWfpJza6EMteSxMDY8_6xIV7HnKaUqmykIQ"
}
`
testCases := []struct {
@ -1026,6 +1033,13 @@ func TestParseJWSRequest(t *testing.T) {
WantErrDetail: "JWS \"signatures\" field not allowed. Only the \"signature\" field should contain a signature",
WantStatType: "JWSMultiSig",
},
{
Name: "JWS with an invalid algorithm",
Request: makePostRequestWithPath("test-path", wrongSignatureTypeJWSBody),
WantErrType: berrors.BadSignatureAlgorithm,
WantErrDetail: "JWS signature header contains unsupported algorithm \"HS256\", expected one of [RS256 ES256 ES384 ES512]",
WantStatType: "JWSAlgorithmCheckFailed",
},
{
Name: "Valid JWS in POST request",
Request: validJWSRequest,