boulder/wfe/jose.go

59 lines
1.8 KiB
Go

package wfe
import (
"crypto/ecdsa"
"crypto/rsa"
"fmt"
"github.com/letsencrypt/boulder/core"
"gopkg.in/square/go-jose.v1"
)
func algorithmForKey(key *jose.JsonWebKey) (string, error) {
switch k := key.Key.(type) {
case *rsa.PublicKey:
return string(jose.RS256), nil
case *ecdsa.PublicKey:
switch k.Params().Name {
case "P-256":
return string(jose.ES256), nil
case "P-384":
return string(jose.ES384), nil
case "P-521":
return string(jose.ES512), nil
}
}
return "", core.SignatureValidationError("no signature algorithms suitable for given key type")
}
const (
noAlgorithmForKey = "WFE.Errors.NoAlgorithmForKey"
invalidJWSAlgorithm = "WFE.Errors.InvalidJWSAlgorithm"
invalidAlgorithmOnKey = "WFE.Errors.InvalidAlgorithmOnKey"
)
// Check that (1) there is a suitable algorithm for the provided key based on its
// Golang type, (2) the Algorithm field on the JWK is either absent, or matches
// that algorithm, and (3) the Algorithm field on the JWK is present and matches
// that algorithm. Precondition: parsedJws must have exactly one signature on
// it. Returns stat name to increment if err is non-nil.
func checkAlgorithm(key *jose.JsonWebKey, parsedJws *jose.JsonWebSignature) (string, error) {
algorithm, err := algorithmForKey(key)
if err != nil {
return noAlgorithmForKey, err
}
jwsAlgorithm := parsedJws.Signatures[0].Header.Algorithm
if jwsAlgorithm != algorithm {
return invalidJWSAlgorithm,
core.SignatureValidationError(fmt.Sprintf(
"signature type '%s' in JWS header is not supported, expected one of RS256, ES256, ES384 or ES512",
jwsAlgorithm))
}
if key.Algorithm != "" && key.Algorithm != algorithm {
return invalidAlgorithmOnKey,
core.SignatureValidationError(fmt.Sprintf(
"algorithm '%s' on JWK is unacceptable", key.Algorithm))
}
return "", nil
}