mirror of
https://github.com/docker/cli.git
synced 2026-09-27 01:40:31 -04:00
Merge pull request #7288 from thaJeztah/bump_jose
vendor: github.com/go-jose/go-jose/v4 v4.1.5
This commit is contained in:
+1
-1
@@ -25,7 +25,7 @@ require (
|
||||
github.com/docker/go-connections v0.8.1
|
||||
github.com/docker/go-units v0.5.0
|
||||
github.com/fvbommel/sortorder v1.2.0
|
||||
github.com/go-jose/go-jose/v4 v4.1.4
|
||||
github.com/go-jose/go-jose/v4 v4.1.5
|
||||
github.com/go-viper/mapstructure/v2 v2.5.0
|
||||
github.com/gogo/protobuf v1.3.2
|
||||
github.com/google/go-cmp v0.7.0
|
||||
|
||||
+2
-2
@@ -51,8 +51,8 @@ github.com/felixge/httpsnoop v1.1.0 h1:3YtUj32ZZkqZtt3sZZsClsymw/QDuVfpNhoA31zeO
|
||||
github.com/felixge/httpsnoop v1.1.0/go.mod h1:Zqxgdd+1Rkcz8euOqdr7lqgCRJztwr5hp9vDSi5UZCE=
|
||||
github.com/fvbommel/sortorder v1.2.0 h1:TRIiRiGX+djh3Yf4FVxmWmAcYfIr5dH0NbzJWOSAWZk=
|
||||
github.com/fvbommel/sortorder v1.2.0/go.mod h1:LbhO04ijZIeUuvz9B9BkI/qYrpZZEn1gWhxv4QjUKVs=
|
||||
github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA=
|
||||
github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08=
|
||||
github.com/go-jose/go-jose/v4 v4.1.5 h1:RjgjO2LOtWOJKUC5wpwY9LR3B3vwVAz6JS2YHfYU6eA=
|
||||
github.com/go-jose/go-jose/v4 v4.1.5/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.4.4 h1:tG4xh9yMsRCAiodLVTxyrkzSZ9+o0L1Kg/+cPVcbP/8=
|
||||
github.com/go-logr/logr v1.4.4/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
|
||||
+18
-8
@@ -21,6 +21,7 @@ import (
|
||||
"crypto/aes"
|
||||
"crypto/ecdsa"
|
||||
"crypto/ed25519"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/sha1"
|
||||
@@ -195,11 +196,11 @@ func (ctx rsaEncrypterVerifier) encryptKey(cek []byte, alg KeyAlgorithm) (recipi
|
||||
func (ctx rsaEncrypterVerifier) encrypt(cek []byte, alg KeyAlgorithm) ([]byte, error) {
|
||||
switch alg {
|
||||
case RSA1_5:
|
||||
return rsa.EncryptPKCS1v15(RandReader, ctx.publicKey, cek)
|
||||
return rsa.EncryptPKCS1v15(randReader, ctx.publicKey, cek)
|
||||
case RSA_OAEP:
|
||||
return rsa.EncryptOAEP(sha1.New(), RandReader, ctx.publicKey, cek, []byte{})
|
||||
return rsa.EncryptOAEP(sha1.New(), randReader, ctx.publicKey, cek, []byte{})
|
||||
case RSA_OAEP_256:
|
||||
return rsa.EncryptOAEP(sha256.New(), RandReader, ctx.publicKey, cek, []byte{})
|
||||
return rsa.EncryptOAEP(sha256.New(), randReader, ctx.publicKey, cek, []byte{})
|
||||
}
|
||||
|
||||
return nil, ErrUnsupportedAlgorithm
|
||||
@@ -288,9 +289,9 @@ func (ctx rsaDecrypterSigner) signPayload(payload []byte, alg SignatureAlgorithm
|
||||
// TODO(https://github.com/go-jose/go-jose/issues/40): As of go1.20, the
|
||||
// random parameter is legacy and ignored, and it can be nil.
|
||||
// https://cs.opensource.google/go/go/+/refs/tags/go1.20:src/crypto/rsa/pkcs1v15.go;l=263;bpv=0;bpt=1
|
||||
out, err = rsa.SignPKCS1v15(RandReader, ctx.privateKey, hash, hashed)
|
||||
out, err = rsa.SignPKCS1v15(randReader, ctx.privateKey, hash, hashed)
|
||||
case PS256, PS384, PS512:
|
||||
out, err = rsa.SignPSS(RandReader, ctx.privateKey, hash, hashed, &rsa.PSSOptions{
|
||||
out, err = rsa.SignPSS(randReader, ctx.privateKey, hash, hashed, &rsa.PSSOptions{
|
||||
SaltLength: rsa.PSSSaltLengthEqualsHash,
|
||||
})
|
||||
}
|
||||
@@ -391,7 +392,7 @@ func (ctx ecKeyGenerator) keySize() int {
|
||||
|
||||
// Get a content encryption key for ECDH-ES
|
||||
func (ctx ecKeyGenerator) genKey() ([]byte, rawHeader, error) {
|
||||
priv, err := ecdsa.GenerateKey(ctx.publicKey.Curve, RandReader)
|
||||
priv, err := ecdsa.GenerateKey(ctx.publicKey.Curve, randReader)
|
||||
if err != nil {
|
||||
return nil, rawHeader{}, err
|
||||
}
|
||||
@@ -483,7 +484,7 @@ func (ctx edDecrypterSigner) signPayload(payload []byte, alg SignatureAlgorithm)
|
||||
return Signature{}, ErrUnsupportedAlgorithm
|
||||
}
|
||||
|
||||
sig, err := ctx.privateKey.Sign(RandReader, payload, crypto.Hash(0))
|
||||
sig, err := ctx.privateKey.Sign(randReader, payload, crypto.Hash(0))
|
||||
if err != nil {
|
||||
return Signature{}, err
|
||||
}
|
||||
@@ -533,7 +534,7 @@ func (ctx ecDecrypterSigner) signPayload(payload []byte, alg SignatureAlgorithm)
|
||||
_, _ = hasher.Write(payload)
|
||||
hashed := hasher.Sum(nil)
|
||||
|
||||
r, s, err := ecdsa.Sign(RandReader, ctx.privateKey, hashed)
|
||||
r, s, err := ecdsa.Sign(randReader, ctx.privateKey, hashed)
|
||||
if err != nil {
|
||||
return Signature{}, err
|
||||
}
|
||||
@@ -571,12 +572,21 @@ func (ctx ecEncrypterVerifier) verifyPayload(payload []byte, signature []byte, a
|
||||
case ES256:
|
||||
keySize = 32
|
||||
hash = crypto.SHA256
|
||||
if ctx.publicKey.Curve != elliptic.P256() {
|
||||
return fmt.Errorf("go-jose/go-jose: signature uses different algorithm than public key")
|
||||
}
|
||||
case ES384:
|
||||
keySize = 48
|
||||
hash = crypto.SHA384
|
||||
if ctx.publicKey.Curve != elliptic.P384() {
|
||||
return fmt.Errorf("go-jose/go-jose: signature uses different algorithm than public key")
|
||||
}
|
||||
case ES512:
|
||||
keySize = 66
|
||||
hash = crypto.SHA512
|
||||
if ctx.publicKey.Curve != elliptic.P521() {
|
||||
return fmt.Errorf("go-jose/go-jose: signature uses different algorithm than public key")
|
||||
}
|
||||
default:
|
||||
return ErrUnsupportedAlgorithm
|
||||
}
|
||||
|
||||
+5
-1
@@ -51,6 +51,8 @@ func NewCBCHMAC(key []byte, newBlockCipher func([]byte) (cipher.Block, error)) (
|
||||
hash = sha512.New384
|
||||
case 32:
|
||||
hash = sha512.New
|
||||
default:
|
||||
return nil, errors.New("go-jose/go-jose: invalid key size for CBC-HMAC")
|
||||
}
|
||||
|
||||
return &cbcAEAD{
|
||||
@@ -176,7 +178,9 @@ func padBuffer(buffer []byte, blockSize int) []byte {
|
||||
|
||||
// Remove padding
|
||||
func unpadBuffer(buffer []byte, blockSize int) ([]byte, error) {
|
||||
if len(buffer)%blockSize != 0 {
|
||||
// A padded buffer can't be empty because an empty input is padded with
|
||||
// `blockSize` bytes, resulting in a non-empty ciphertext.
|
||||
if len(buffer) == 0 || len(buffer)%blockSize != 0 {
|
||||
return nil, errors.New("go-jose/go-jose: invalid padding")
|
||||
}
|
||||
|
||||
|
||||
+58
-32
@@ -258,6 +258,10 @@ func (ctx *genericEncrypter) addRecipient(recipient Recipient) (err error) {
|
||||
}
|
||||
|
||||
recipientInfo, err = makeJWERecipient(recipient.Algorithm, recipient.Key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if recipient.KeyID != "" {
|
||||
recipientInfo.keyID = recipient.KeyID
|
||||
}
|
||||
@@ -270,10 +274,8 @@ func (ctx *genericEncrypter) addRecipient(recipient Recipient) (err error) {
|
||||
}
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
ctx.recipients = append(ctx.recipients, recipientInfo)
|
||||
}
|
||||
return err
|
||||
ctx.recipients = append(ctx.recipients, recipientInfo)
|
||||
return nil
|
||||
}
|
||||
|
||||
func makeJWERecipient(alg KeyAlgorithm, encryptionKey interface{}) (recipientKeyInfo, error) {
|
||||
@@ -490,21 +492,19 @@ func (obj JSONWebEncryption) Decrypt(decryptionKey interface{}) ([]byte, error)
|
||||
recipientHeaders := obj.mergedHeaders(&recipient)
|
||||
|
||||
cek, err := decrypter.decryptKey(recipientHeaders, &recipient, generator)
|
||||
if err == nil {
|
||||
// Found a valid CEK -- let's try to decrypt.
|
||||
plaintext, err = cipher.decrypt(cek, authData, parts)
|
||||
}
|
||||
|
||||
if plaintext == nil {
|
||||
if err != nil {
|
||||
return nil, ErrCryptoFailure
|
||||
}
|
||||
|
||||
// The "zip" header parameter may only be present in the protected header.
|
||||
if comp := obj.protected.getCompression(); comp != "" {
|
||||
plaintext, err = decompress(comp, plaintext)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: failed to decompress plaintext: %v", err)
|
||||
}
|
||||
// Found a valid CEK -- let's try to decrypt.
|
||||
plaintext, err = cipher.decrypt(cek, authData, parts)
|
||||
if err != nil {
|
||||
return nil, ErrCryptoFailure
|
||||
}
|
||||
|
||||
plaintext, err = obj.decompress(plaintext)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return plaintext, nil
|
||||
@@ -559,31 +559,38 @@ func (obj JSONWebEncryption) DecryptMulti(decryptionKey interface{}) (int, Heade
|
||||
var plaintext []byte
|
||||
var headers rawHeader
|
||||
|
||||
if len(obj.recipients) == 0 {
|
||||
return -1, Header{}, nil, errors.New("go-jose/go-jose: no recipients")
|
||||
}
|
||||
|
||||
// Loop sets `err` in the function scope; don't shadow it.
|
||||
for i, recipient := range obj.recipients {
|
||||
recipientHeaders := obj.mergedHeaders(&recipient)
|
||||
|
||||
cek, err := decrypter.decryptKey(recipientHeaders, &recipient, generator)
|
||||
if err == nil {
|
||||
// Found a valid CEK -- let's try to decrypt.
|
||||
plaintext, err = cipher.decrypt(cek, authData, parts)
|
||||
if err == nil {
|
||||
index = i
|
||||
headers = recipientHeaders
|
||||
break
|
||||
}
|
||||
var cek []byte
|
||||
cek, err = decrypter.decryptKey(recipientHeaders, &recipient, generator)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Found a valid CEK -- let's try to decrypt.
|
||||
plaintext, err = cipher.decrypt(cek, authData, parts)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
index = i
|
||||
headers = recipientHeaders
|
||||
break
|
||||
}
|
||||
|
||||
if plaintext == nil {
|
||||
if err != nil {
|
||||
return -1, Header{}, nil, ErrCryptoFailure
|
||||
}
|
||||
|
||||
// The "zip" header parameter may only be present in the protected header.
|
||||
if comp := obj.protected.getCompression(); comp != "" {
|
||||
plaintext, err = decompress(comp, plaintext)
|
||||
if err != nil {
|
||||
return -1, Header{}, nil, fmt.Errorf("go-jose/go-jose: failed to decompress plaintext: %v", err)
|
||||
}
|
||||
plaintext, err = obj.decompress(plaintext)
|
||||
if err != nil {
|
||||
return -1, Header{}, nil, err
|
||||
}
|
||||
|
||||
sanitized, err := headers.sanitized()
|
||||
@@ -593,3 +600,22 @@ func (obj JSONWebEncryption) DecryptMulti(decryptionKey interface{}) (int, Heade
|
||||
|
||||
return index, sanitized, plaintext, err
|
||||
}
|
||||
|
||||
// decompress decompresses plaintext using the protected "zip" header, if present.
|
||||
// It returns plaintext unchanged when there is no protected header or "zip" value.
|
||||
func (obj JSONWebEncryption) decompress(plaintext []byte) ([]byte, error) {
|
||||
if obj.protected == nil {
|
||||
return plaintext, nil
|
||||
}
|
||||
|
||||
comp := obj.protected.getCompression()
|
||||
if comp == "" {
|
||||
return plaintext, nil
|
||||
}
|
||||
|
||||
plaintext, err := decompress(comp, plaintext)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: failed to decompress plaintext: %v", err)
|
||||
}
|
||||
return plaintext, nil
|
||||
}
|
||||
|
||||
+13
-6
@@ -140,6 +140,10 @@ const (
|
||||
parseArrayValue // parsing array value
|
||||
)
|
||||
|
||||
// This limits the max nesting depth to prevent stack overflow.
|
||||
// This is permitted by https://tools.ietf.org/html/rfc7159#section-9
|
||||
const maxNestingDepth = 10000
|
||||
|
||||
// reset prepares the scanner for use.
|
||||
// It must be called before calling s.step.
|
||||
func (s *scanner) reset() {
|
||||
@@ -170,8 +174,13 @@ func (s *scanner) eof() int {
|
||||
}
|
||||
|
||||
// pushParseState pushes a new parse state p onto the parse stack.
|
||||
func (s *scanner) pushParseState(p int) {
|
||||
s.parseState = append(s.parseState, p)
|
||||
// an error state is returned if maxNestingDepth was exceeded, otherwise successState is returned.
|
||||
func (s *scanner) pushParseState(c byte, newParseState int, successState int) int {
|
||||
s.parseState = append(s.parseState, newParseState)
|
||||
if len(s.parseState) <= maxNestingDepth {
|
||||
return successState
|
||||
}
|
||||
return s.error(c, "exceeded max depth")
|
||||
}
|
||||
|
||||
// popParseState pops a parse state (already obtained) off the stack
|
||||
@@ -211,12 +220,10 @@ func stateBeginValue(s *scanner, c byte) int {
|
||||
switch c {
|
||||
case '{':
|
||||
s.step = stateBeginStringOrEmpty
|
||||
s.pushParseState(parseObjectKey)
|
||||
return scanBeginObject
|
||||
return s.pushParseState(c, parseObjectKey, scanBeginObject)
|
||||
case '[':
|
||||
s.step = stateBeginValueOrEmpty
|
||||
s.pushParseState(parseArrayValue)
|
||||
return scanBeginArray
|
||||
return s.pushParseState(c, parseArrayValue, scanBeginArray)
|
||||
case '"':
|
||||
s.step = stateInString
|
||||
return scanBeginLiteral
|
||||
|
||||
+8
@@ -153,6 +153,10 @@ func ParseEncryptedJSON(
|
||||
keyEncryptionAlgorithms []KeyAlgorithm,
|
||||
contentEncryption []ContentEncryption,
|
||||
) (*JSONWebEncryption, error) {
|
||||
if len(input) == 0 {
|
||||
return nil, errEmptyInput
|
||||
}
|
||||
|
||||
var parsed rawJSONWebEncryption
|
||||
err := json.Unmarshal([]byte(input), &parsed)
|
||||
if err != nil {
|
||||
@@ -291,6 +295,10 @@ func ParseEncryptedCompact(
|
||||
var parts [5]string
|
||||
var ok bool
|
||||
|
||||
if len(input) == 0 {
|
||||
return nil, errEmptyInput
|
||||
}
|
||||
|
||||
for i := range 4 {
|
||||
parts[i], input, ok = strings.Cut(input, ".")
|
||||
if !ok {
|
||||
|
||||
+174
-39
@@ -107,7 +107,7 @@ func (k JSONWebKey) MarshalJSON() ([]byte, error) {
|
||||
|
||||
switch key := k.Key.(type) {
|
||||
case ed25519.PublicKey:
|
||||
raw = fromEdPublicKey(key)
|
||||
raw, err = fromEdPublicKey(key)
|
||||
case *ecdsa.PublicKey:
|
||||
raw, err = fromEcPublicKey(key)
|
||||
case *rsa.PublicKey:
|
||||
@@ -207,21 +207,29 @@ func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) {
|
||||
case "EC":
|
||||
if raw.D != nil {
|
||||
key, err = raw.ecPrivateKey()
|
||||
if err == nil {
|
||||
keyPub = key.(*ecdsa.PrivateKey).Public()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
keyPub = key.(*ecdsa.PrivateKey).Public()
|
||||
} else {
|
||||
key, err = raw.ecPublicKey()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
keyPub = key
|
||||
}
|
||||
case "RSA":
|
||||
if raw.D != nil {
|
||||
key, err = raw.rsaPrivateKey()
|
||||
if err == nil {
|
||||
keyPub = key.(*rsa.PrivateKey).Public()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
keyPub = key.(*rsa.PrivateKey).Public()
|
||||
} else {
|
||||
key, err = raw.rsaPublicKey()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
keyPub = key
|
||||
}
|
||||
case "oct":
|
||||
@@ -229,25 +237,28 @@ func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) {
|
||||
return errors.New("go-jose/go-jose: invalid JWK, found 'oct' (symmetric) key with cert chain")
|
||||
}
|
||||
key, err = raw.symmetricKey()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case "OKP":
|
||||
if raw.Crv == "Ed25519" {
|
||||
if raw.D != nil {
|
||||
key, err = raw.edPrivateKey()
|
||||
if err == nil {
|
||||
keyPub = key.(ed25519.PrivateKey).Public()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
keyPub = key.(ed25519.PrivateKey).Public()
|
||||
} else {
|
||||
key, err = raw.edPublicKey()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
keyPub = key
|
||||
}
|
||||
}
|
||||
case "":
|
||||
// kty MUST be present
|
||||
err = fmt.Errorf("go-jose/go-jose: missing json web key type")
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
return fmt.Errorf("go-jose/go-jose: missing json web key type")
|
||||
}
|
||||
|
||||
if key == nil {
|
||||
@@ -388,11 +399,12 @@ func rsaThumbprintInput(n *big.Int, e int) (string, error) {
|
||||
|
||||
func edThumbprintInput(ed ed25519.PublicKey) (string, error) {
|
||||
crv := "Ed25519"
|
||||
if len(ed) > 32 {
|
||||
return "", errors.New("go-jose/go-jose: invalid elliptic key (too large)")
|
||||
err := validateEd25519PublicKey(ed)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return fmt.Sprintf(edThumbprintTemplate, crv,
|
||||
newFixedSizeBuffer(ed, 32).base64()), nil
|
||||
newFixedSizeBuffer(ed, ed25519.PublicKeySize).base64()), nil
|
||||
}
|
||||
|
||||
// Thumbprint computes the JWK Thumbprint of a key using the
|
||||
@@ -504,12 +516,16 @@ func (key rawJSONWebKey) rsaPublicKey() (*rsa.PublicKey, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func fromEdPublicKey(pub ed25519.PublicKey) *rawJSONWebKey {
|
||||
func fromEdPublicKey(pub ed25519.PublicKey) (*rawJSONWebKey, error) {
|
||||
err := validateEd25519PublicKey(pub)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &rawJSONWebKey{
|
||||
Kty: "OKP",
|
||||
Crv: "Ed25519",
|
||||
X: newBuffer(pub),
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
||||
func fromRsaPublicKey(pub *rsa.PublicKey) *rawJSONWebKey {
|
||||
@@ -604,21 +620,36 @@ func (key rawJSONWebKey) edPrivateKey() (ed25519.PrivateKey, error) {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid Ed25519 private key, missing %s value(s)", strings.Join(missing, ", "))
|
||||
}
|
||||
|
||||
privateKey := make([]byte, ed25519.PrivateKeySize)
|
||||
copy(privateKey[0:32], key.D.bytes())
|
||||
copy(privateKey[32:], key.X.bytes())
|
||||
rv := ed25519.PrivateKey(privateKey)
|
||||
return rv, nil
|
||||
publicKey := key.X.bytes()
|
||||
err := validateEd25519PublicKey(publicKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
seed := key.D.bytes()
|
||||
if len(seed) != ed25519.SeedSize {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid Ed25519 private key, wrong length for d")
|
||||
}
|
||||
|
||||
privateKey := ed25519.NewKeyFromSeed(seed)
|
||||
derivedPublicKey := privateKey.Public().(ed25519.PublicKey)
|
||||
if !bytes.Equal(derivedPublicKey, publicKey) {
|
||||
return nil, errors.New("go-jose/go-jose: invalid Ed25519 private key, x does not match d")
|
||||
}
|
||||
|
||||
return privateKey, nil
|
||||
}
|
||||
|
||||
func (key rawJSONWebKey) edPublicKey() (ed25519.PublicKey, error) {
|
||||
if key.X == nil {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid Ed key, missing x value")
|
||||
}
|
||||
publicKey := make([]byte, ed25519.PublicKeySize)
|
||||
copy(publicKey[0:32], key.X.bytes())
|
||||
rv := ed25519.PublicKey(publicKey)
|
||||
return rv, nil
|
||||
publicKey := key.X.bytes()
|
||||
err := validateEd25519PublicKey(publicKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ed25519.PublicKey(bytes.Clone(publicKey)), nil
|
||||
}
|
||||
|
||||
func (key rawJSONWebKey) rsaPrivateKey() (*rsa.PrivateKey, error) {
|
||||
@@ -669,9 +700,17 @@ func (key rawJSONWebKey) rsaPrivateKey() (*rsa.PrivateKey, error) {
|
||||
}
|
||||
|
||||
func fromEdPrivateKey(ed ed25519.PrivateKey) (*rawJSONWebKey, error) {
|
||||
raw := fromEdPublicKey(ed25519.PublicKey(ed[32:]))
|
||||
if len(ed) != ed25519.PrivateKeySize {
|
||||
return nil, errors.New("go-jose/go-jose: invalid Ed25519 private key length")
|
||||
}
|
||||
|
||||
raw.D = newBuffer(ed[0:32])
|
||||
publicKey := ed.Public().(ed25519.PublicKey)
|
||||
raw, err := fromEdPublicKey(publicKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
raw.D = newBuffer(ed.Seed())
|
||||
return raw, nil
|
||||
}
|
||||
|
||||
@@ -810,7 +849,7 @@ var (
|
||||
ErrJWKSKidNotFound = errors.New("go-jose/go-jose: JWK with matching kid not found in JWK Set")
|
||||
)
|
||||
|
||||
func tryJWKS(key interface{}, headers ...Header) (interface{}, error) {
|
||||
func tryJWKS(key interface{}, header Header) (interface{}, error) {
|
||||
var jwks JSONWebKeySet
|
||||
|
||||
switch jwksType := key.(type) {
|
||||
@@ -823,16 +862,8 @@ func tryJWKS(key interface{}, headers ...Header) (interface{}, error) {
|
||||
return key, nil
|
||||
}
|
||||
|
||||
// Determine the KID to search for from the headers.
|
||||
var kid string
|
||||
for _, header := range headers {
|
||||
if header.KeyID != "" {
|
||||
kid = header.KeyID
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// If no KID is specified in the headers, reject.
|
||||
// If no KID is specified in the header, reject.
|
||||
kid := header.KeyID
|
||||
if kid == "" {
|
||||
return nil, ErrJWKSKidNotFound
|
||||
}
|
||||
@@ -846,3 +877,107 @@ func tryJWKS(key interface{}, headers ...Header) (interface{}, error) {
|
||||
|
||||
return keys[0].Key, nil
|
||||
}
|
||||
|
||||
// weakEd25519PublicKeys contains the low-order Ed25519 encodings accepted by
|
||||
// Go's verifier that must not be accepted as JOSE verification keys.
|
||||
var weakEd25519PublicKeys = map[[ed25519.PublicKeySize]byte]struct{}{
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
}: {},
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
|
||||
}: {},
|
||||
{
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
}: {},
|
||||
{
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
|
||||
}: {},
|
||||
{
|
||||
0x26, 0xe8, 0x95, 0x8f, 0xc2, 0xb2, 0x27, 0xb0,
|
||||
0x45, 0xc3, 0xf4, 0x89, 0xf2, 0xef, 0x98, 0xf0,
|
||||
0xd5, 0xdf, 0xac, 0x05, 0xd3, 0xc6, 0x33, 0x39,
|
||||
0xb1, 0x38, 0x02, 0x88, 0x6d, 0x53, 0xfc, 0x05,
|
||||
}: {},
|
||||
{
|
||||
0x26, 0xe8, 0x95, 0x8f, 0xc2, 0xb2, 0x27, 0xb0,
|
||||
0x45, 0xc3, 0xf4, 0x89, 0xf2, 0xef, 0x98, 0xf0,
|
||||
0xd5, 0xdf, 0xac, 0x05, 0xd3, 0xc6, 0x33, 0x39,
|
||||
0xb1, 0x38, 0x02, 0x88, 0x6d, 0x53, 0xfc, 0x85,
|
||||
}: {},
|
||||
{
|
||||
0xc7, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f,
|
||||
0xba, 0x3c, 0x0b, 0x76, 0x0d, 0x10, 0x67, 0x0f,
|
||||
0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39, 0xcc, 0xc6,
|
||||
0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0x7a,
|
||||
}: {},
|
||||
{
|
||||
0xc7, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f,
|
||||
0xba, 0x3c, 0x0b, 0x76, 0x0d, 0x10, 0x67, 0x0f,
|
||||
0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39, 0xcc, 0xc6,
|
||||
0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0xfa,
|
||||
}: {},
|
||||
{
|
||||
0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
|
||||
}: {},
|
||||
{
|
||||
0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
}: {},
|
||||
{
|
||||
0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
|
||||
}: {},
|
||||
{
|
||||
0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
}: {},
|
||||
{
|
||||
0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
|
||||
}: {},
|
||||
{
|
||||
0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
}: {},
|
||||
}
|
||||
|
||||
func validateEd25519PublicKey(publicKey ed25519.PublicKey) error {
|
||||
if len(publicKey) != ed25519.PublicKeySize {
|
||||
return fmt.Errorf("go-jose/go-jose: invalid Ed25519 public key, wrong length for x")
|
||||
}
|
||||
|
||||
var encoded [ed25519.PublicKeySize]byte
|
||||
copy(encoded[:], publicKey)
|
||||
_, ok := weakEd25519PublicKeys[encoded]
|
||||
if ok {
|
||||
return errors.New("go-jose/go-jose: invalid Ed25519 public key, low-order point")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
+12
-3
@@ -22,6 +22,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"github.com/go-jose/go-jose/v4/json"
|
||||
)
|
||||
@@ -89,12 +90,12 @@ func ParseSigned(
|
||||
signature string,
|
||||
signatureAlgorithms []SignatureAlgorithm,
|
||||
) (*JSONWebSignature, error) {
|
||||
signature = stripWhitespace(signature)
|
||||
if strings.HasPrefix(signature, "{") {
|
||||
trimmed := strings.TrimLeftFunc(signature, unicode.IsSpace)
|
||||
if strings.HasPrefix(trimmed, "{") {
|
||||
return ParseSignedJSON(signature, signatureAlgorithms)
|
||||
}
|
||||
|
||||
return parseSignedCompact(signature, nil, signatureAlgorithms)
|
||||
return parseSignedCompact(stripWhitespace(signature), nil, signatureAlgorithms)
|
||||
}
|
||||
|
||||
// ParseSignedCompact parses a message in JWS Compact Serialization. Validation fails if the JWS is
|
||||
@@ -186,6 +187,10 @@ func ParseSignedJSON(
|
||||
input string,
|
||||
signatureAlgorithms []SignatureAlgorithm,
|
||||
) (*JSONWebSignature, error) {
|
||||
if len(input) == 0 {
|
||||
return nil, errEmptyInput
|
||||
}
|
||||
|
||||
var parsed rawJSONWebSignature
|
||||
err := json.Unmarshal([]byte(input), &parsed)
|
||||
if err != nil {
|
||||
@@ -369,6 +374,10 @@ func parseSignedCompact(
|
||||
payload []byte,
|
||||
signatureAlgorithms []SignatureAlgorithm,
|
||||
) (*JSONWebSignature, error) {
|
||||
if len(input) == 0 {
|
||||
return nil, errEmptyInput
|
||||
}
|
||||
|
||||
protected, s, ok := strings.Cut(input, tokenDelim)
|
||||
if !ok { // no period found
|
||||
return nil, fmt.Errorf("go-jose/go-jose: compact JWS format must have three parts")
|
||||
|
||||
+15
@@ -24,6 +24,11 @@ import (
|
||||
"github.com/go-jose/go-jose/v4/json"
|
||||
)
|
||||
|
||||
// maxNumericDate bounds an accepted NumericDate (in seconds). It is far past
|
||||
// any real timestamp but safely below where an int64 conversion or time.Unix
|
||||
// would overflow and wrap Time() to a bogus instant.
|
||||
const maxNumericDate = 1 << 62
|
||||
|
||||
// Claims represents public claim values (as specified in RFC 7519).
|
||||
type Claims struct {
|
||||
Issuer string `json:"iss,omitempty"`
|
||||
@@ -69,6 +74,16 @@ func (n *NumericDate) UnmarshalJSON(b []byte) error {
|
||||
return ErrUnmarshalNumericDate
|
||||
}
|
||||
|
||||
// Reject values large enough to overflow either the int64 conversion below
|
||||
// or time.Unix in Time(). time.Unix adds a ~62e9-second offset internally,
|
||||
// so a value near the int64 limit wraps and compares as a time in the
|
||||
// past; for "nbf" that lets a not-yet-valid token pass the not-before
|
||||
// check instead of being rejected. maxNumericDate (2^62 seconds) is far
|
||||
// beyond any real timestamp yet safely below both overflow points.
|
||||
if f >= maxNumericDate || f <= -maxNumericDate {
|
||||
return ErrUnmarshalNumericDate
|
||||
}
|
||||
|
||||
*n = NumericDate(f)
|
||||
return nil
|
||||
}
|
||||
|
||||
+5
@@ -46,6 +46,11 @@ func newOpaqueSigner(alg SignatureAlgorithm, signer OpaqueSigner) (recipientSigI
|
||||
return recipientSigInfo{}, ErrUnsupportedAlgorithm
|
||||
}
|
||||
|
||||
pk := signer.Public()
|
||||
if pk != nil && !pk.IsPublic() {
|
||||
return recipientSigInfo{}, ErrNotPublic
|
||||
}
|
||||
|
||||
return recipientSigInfo{
|
||||
sigAlg: alg,
|
||||
publicKey: signer.Public,
|
||||
|
||||
+6
@@ -80,6 +80,12 @@ var (
|
||||
|
||||
// ErrUnsupportedCriticalHeader is returned when a header is marked critical but not supported by go-jose.
|
||||
ErrUnsupportedCriticalHeader = errors.New("go-jose/go-jose: unsupported critical header")
|
||||
|
||||
// errEmptyInput is returned when go-jose was asked to parse an empty string.
|
||||
errEmptyInput = errors.New("go-jose/go-jose: empty input")
|
||||
|
||||
// ErrNotPublic indicates a private key was passed where a public key was expected
|
||||
ErrNotPublic = errors.New("go-jose/go-jose: public key was unexpectedly not public")
|
||||
)
|
||||
|
||||
// Key management algorithms
|
||||
|
||||
+65
-46
@@ -130,6 +130,8 @@ type payloadVerifier interface {
|
||||
verifyPayload(payload []byte, signature []byte, alg SignatureAlgorithm) error
|
||||
}
|
||||
|
||||
var errInvalidVerificationKey = errors.New("go-jose/go-jose: invalid verification key")
|
||||
|
||||
type genericSigner struct {
|
||||
recipients []recipientSigInfo
|
||||
nonceSource NonceSource
|
||||
@@ -138,11 +140,21 @@ type genericSigner struct {
|
||||
}
|
||||
|
||||
type recipientSigInfo struct {
|
||||
sigAlg SignatureAlgorithm
|
||||
sigAlg SignatureAlgorithm
|
||||
// publicKey returns a synthetic JSONWebKey for the signer.
|
||||
// For opaque signers, it calls OpaqueSigner.Public().
|
||||
publicKey func() *JSONWebKey
|
||||
signer payloadSigner
|
||||
}
|
||||
|
||||
// getPublicKey gets the public key, with a nil check on the func.
|
||||
func (r recipientSigInfo) getPublicKey() *JSONWebKey {
|
||||
if r.publicKey == nil {
|
||||
return nil
|
||||
}
|
||||
return r.publicKey()
|
||||
}
|
||||
|
||||
func staticPublicKey(jwk *JSONWebKey) func() *JSONWebKey {
|
||||
return func() *JSONWebKey {
|
||||
return jwk
|
||||
@@ -178,14 +190,23 @@ func NewMultiSigner(sigs []SigningKey, opts *SignerOptions) (Signer, error) {
|
||||
func newVerifier(verificationKey interface{}) (payloadVerifier, error) {
|
||||
switch verificationKey := verificationKey.(type) {
|
||||
case ed25519.PublicKey:
|
||||
if len(verificationKey) == 0 {
|
||||
return nil, errInvalidVerificationKey
|
||||
}
|
||||
return &edEncrypterVerifier{
|
||||
publicKey: verificationKey,
|
||||
}, nil
|
||||
case *rsa.PublicKey:
|
||||
if verificationKey == nil {
|
||||
return nil, errInvalidVerificationKey
|
||||
}
|
||||
return &rsaEncrypterVerifier{
|
||||
publicKey: verificationKey,
|
||||
}, nil
|
||||
case *ecdsa.PublicKey:
|
||||
if verificationKey == nil {
|
||||
return nil, errInvalidVerificationKey
|
||||
}
|
||||
return &ecEncrypterVerifier{
|
||||
publicKey: verificationKey,
|
||||
}, nil
|
||||
@@ -196,6 +217,9 @@ func newVerifier(verificationKey interface{}) (payloadVerifier, error) {
|
||||
case JSONWebKey:
|
||||
return newVerifier(verificationKey.Key)
|
||||
case *JSONWebKey:
|
||||
if verificationKey == nil {
|
||||
return nil, errInvalidVerificationKey
|
||||
}
|
||||
return newVerifier(verificationKey.Key)
|
||||
case OpaqueVerifier:
|
||||
return &opaqueVerifier{verifier: verificationKey}, nil
|
||||
@@ -240,18 +264,18 @@ func newJWKSigner(alg SignatureAlgorithm, signingKey JSONWebKey) (recipientSigIn
|
||||
if err != nil {
|
||||
return recipientSigInfo{}, err
|
||||
}
|
||||
if recipient.publicKey != nil && recipient.publicKey() != nil {
|
||||
if recipientPubKey := recipient.getPublicKey(); recipientPubKey != nil {
|
||||
// This should be impossible, but let's check anyway.
|
||||
if !recipientPubKey.IsPublic() {
|
||||
return recipientSigInfo{}, ErrNotPublic
|
||||
}
|
||||
|
||||
// recipient.publicKey is a JWK synthesized for embedding when recipientSigInfo
|
||||
// was created for the inner key (such as a RSA or ECDSA public key). It contains
|
||||
// the pub key for embedding, but doesn't have extra params like key id.
|
||||
publicKey := signingKey
|
||||
publicKey.Key = recipient.publicKey().Key
|
||||
publicKey.Key = recipientPubKey.Key
|
||||
recipient.publicKey = staticPublicKey(&publicKey)
|
||||
|
||||
// This should be impossible, but let's check anyway.
|
||||
if !recipient.publicKey().IsPublic() {
|
||||
return recipientSigInfo{}, errors.New("go-jose/go-jose: public key was unexpectedly not public")
|
||||
}
|
||||
}
|
||||
return recipient, nil
|
||||
}
|
||||
@@ -266,7 +290,7 @@ func (ctx *genericSigner) Sign(payload []byte) (*JSONWebSignature, error) {
|
||||
headerAlgorithm: string(recipient.sigAlg),
|
||||
}
|
||||
|
||||
if recipient.publicKey != nil && recipient.publicKey() != nil {
|
||||
if recipientPubKey := recipient.getPublicKey(); recipientPubKey != nil {
|
||||
// We want to embed the JWK or set the kid header, but not both. Having a protected
|
||||
// header that contains an embedded JWK while also simultaneously containing the kid
|
||||
// header is confusing, and at least in ACME the two are considered to be mutually
|
||||
@@ -274,11 +298,11 @@ func (ctx *genericSigner) Sign(payload []byte) (*JSONWebSignature, error) {
|
||||
// result of the JOSE spec. We've decided that this library will only include one or
|
||||
// the other to avoid this confusion.
|
||||
//
|
||||
// See https://github.com/go-jose/go-jose/issues/157 for more context.
|
||||
// See https://github.com/square/go-jose/issues/157 for more context.
|
||||
if ctx.embedJWK {
|
||||
protected[headerJWK] = recipient.publicKey()
|
||||
protected[headerJWK] = recipientPubKey
|
||||
} else {
|
||||
keyID := recipient.publicKey().KeyID
|
||||
keyID := recipientPubKey.KeyID
|
||||
if keyID != "" {
|
||||
protected[headerKeyID] = keyID
|
||||
}
|
||||
@@ -390,7 +414,13 @@ func (obj JSONWebSignature) UnsafePayloadWithoutVerification() []byte {
|
||||
// The verificationKey argument must have one of the types allowed for the
|
||||
// verificationKey argument of JSONWebSignature.Verify().
|
||||
func (obj JSONWebSignature) DetachedVerify(payload []byte, verificationKey interface{}) error {
|
||||
key, err := tryJWKS(verificationKey, obj.headers()...)
|
||||
if len(obj.Signatures) > 1 {
|
||||
return errors.New("go-jose/go-jose: too many signatures in payload; expecting only one")
|
||||
}
|
||||
|
||||
signature := obj.Signatures[0]
|
||||
|
||||
key, err := tryJWKS(verificationKey, signature.Header)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -399,12 +429,6 @@ func (obj JSONWebSignature) DetachedVerify(payload []byte, verificationKey inter
|
||||
return err
|
||||
}
|
||||
|
||||
if len(obj.Signatures) > 1 {
|
||||
return errors.New("go-jose/go-jose: too many signatures in payload; expecting only one")
|
||||
}
|
||||
|
||||
signature := obj.Signatures[0]
|
||||
|
||||
if signature.header != nil {
|
||||
// Per https://www.rfc-editor.org/rfc/rfc7515.html#section-4.1.11,
|
||||
// 4.1.11. "crit" (Critical) Header Parameter
|
||||
@@ -432,11 +456,11 @@ func (obj JSONWebSignature) DetachedVerify(payload []byte, verificationKey inter
|
||||
headers := signature.mergedHeaders()
|
||||
alg := headers.getSignatureAlgorithm()
|
||||
err = verifier.verifyPayload(input, signature.Signature, alg)
|
||||
if err == nil {
|
||||
return nil
|
||||
if err != nil {
|
||||
return ErrCryptoFailure
|
||||
}
|
||||
|
||||
return ErrCryptoFailure
|
||||
return nil
|
||||
}
|
||||
|
||||
// VerifyMulti validates (one of the multiple) signatures on the object and
|
||||
@@ -467,16 +491,6 @@ func (obj JSONWebSignature) VerifyMulti(verificationKey interface{}) (int, Signa
|
||||
// The verificationKey argument must have one of the types allowed for the
|
||||
// verificationKey argument of JSONWebSignature.Verify().
|
||||
func (obj JSONWebSignature) DetachedVerifyMulti(payload []byte, verificationKey interface{}) (int, Signature, error) {
|
||||
key, err := tryJWKS(verificationKey, obj.headers()...)
|
||||
if err != nil {
|
||||
return -1, Signature{}, err
|
||||
}
|
||||
verifier, err := newVerifier(key)
|
||||
if err != nil {
|
||||
return -1, Signature{}, err
|
||||
}
|
||||
|
||||
outer:
|
||||
for i, signature := range obj.Signatures {
|
||||
if signature.header != nil {
|
||||
// Per https://www.rfc-editor.org/rfc/rfc7515.html#section-4.1.11,
|
||||
@@ -484,20 +498,31 @@ outer:
|
||||
// "When used, this Header Parameter MUST be integrity
|
||||
// protected; therefore, it MUST occur only within the JWS
|
||||
// Protected Header."
|
||||
err = signature.header.checkNoCritical()
|
||||
err := signature.header.checkNoCritical()
|
||||
if err != nil {
|
||||
continue outer
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if signature.protected != nil {
|
||||
// Check for only supported critical headers
|
||||
err = signature.protected.checkSupportedCritical(supportedCritical)
|
||||
err := signature.protected.checkSupportedCritical(supportedCritical)
|
||||
if err != nil {
|
||||
continue outer
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// If the verification key is a JWK Set, pick a key based on this signature's
|
||||
// "kid" header. If no match, skip this signature.
|
||||
key, err := tryJWKS(verificationKey, signature.Header)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
verifier, err := newVerifier(key)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
input, err := obj.computeAuthData(payload, &signature)
|
||||
if err != nil {
|
||||
continue
|
||||
@@ -506,18 +531,12 @@ outer:
|
||||
headers := signature.mergedHeaders()
|
||||
alg := headers.getSignatureAlgorithm()
|
||||
err = verifier.verifyPayload(input, signature.Signature, alg)
|
||||
if err == nil {
|
||||
return i, signature, nil
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
return i, signature, nil
|
||||
}
|
||||
|
||||
return -1, Signature{}, ErrCryptoFailure
|
||||
}
|
||||
|
||||
func (obj JSONWebSignature) headers() []Header {
|
||||
headers := make([]Header, len(obj.Signatures))
|
||||
for i, sig := range obj.Signatures {
|
||||
headers[i] = sig.Header
|
||||
}
|
||||
return headers
|
||||
}
|
||||
|
||||
+5
-5
@@ -34,8 +34,8 @@ import (
|
||||
josecipher "github.com/go-jose/go-jose/v4/cipher"
|
||||
)
|
||||
|
||||
// RandReader is a cryptographically secure random number generator (stubbed out in tests).
|
||||
var RandReader = rand.Reader
|
||||
// randReader is a cryptographically secure random number generator (stubbed out in tests).
|
||||
var randReader = rand.Reader
|
||||
|
||||
const (
|
||||
// RFC7518 recommends a minimum of 1,000 iterations:
|
||||
@@ -153,7 +153,7 @@ func getPbkdf2Params(alg KeyAlgorithm) (int, func() hash.Hash) {
|
||||
// getRandomSalt generates a new salt of the given size.
|
||||
func getRandomSalt(size int) ([]byte, error) {
|
||||
salt := make([]byte, size)
|
||||
_, err := io.ReadFull(RandReader, salt)
|
||||
_, err := io.ReadFull(randReader, salt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -198,7 +198,7 @@ func newSymmetricSigner(sigAlg SignatureAlgorithm, key []byte) (recipientSigInfo
|
||||
// Generate a random key for the given content cipher
|
||||
func (ctx randomKeyGenerator) genKey() ([]byte, rawHeader, error) {
|
||||
key := make([]byte, ctx.size)
|
||||
_, err := io.ReadFull(RandReader, key)
|
||||
_, err := io.ReadFull(randReader, key)
|
||||
if err != nil {
|
||||
return nil, rawHeader{}, err
|
||||
}
|
||||
@@ -238,7 +238,7 @@ func (ctx aeadContentCipher) encrypt(key, aad, pt []byte) (*aeadParts, error) {
|
||||
|
||||
// Initialize a new nonce
|
||||
iv := make([]byte, aead.NonceSize())
|
||||
_, err = io.ReadFull(RandReader, iv)
|
||||
_, err = io.ReadFull(randReader, iv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
Vendored
+1
-1
@@ -94,7 +94,7 @@ github.com/felixge/httpsnoop
|
||||
# github.com/fvbommel/sortorder v1.2.0
|
||||
## explicit; go 1.21
|
||||
github.com/fvbommel/sortorder
|
||||
# github.com/go-jose/go-jose/v4 v4.1.4
|
||||
# github.com/go-jose/go-jose/v4 v4.1.5
|
||||
## explicit; go 1.24.0
|
||||
github.com/go-jose/go-jose/v4
|
||||
github.com/go-jose/go-jose/v4/cipher
|
||||
|
||||
Reference in New Issue
Block a user