fix: improve JWS and key verification (#128)

* fix: improve JWS and key verification

* fix: get remote keys if no cached key matches

* fix: get remote keys if no cached key matches

* fix exactMatch

* fix exactMatch

* chore: change default branch name in .releaserc.js
This commit is contained in:
Livio Amstutz 2021-09-14 15:13:44 +02:00 committed by GitHub
parent 2b5b436c41
commit a63fbee93d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 453 additions and 32 deletions

View file

@ -5,6 +5,7 @@ import (
"crypto/ecdsa"
"crypto/ed25519"
"crypto/rsa"
"errors"
"gopkg.in/square/go-jose.v2"
)
@ -13,6 +14,11 @@ const (
KeyUseSignature = "sig"
)
var (
ErrKeyMultiple = errors.New("multiple possible keys match")
ErrKeyNone = errors.New("no possible keys matches")
)
//KeySet represents a set of JSON Web Keys
// - remotely fetch via discovery and jwks_uri -> `remoteKeySet`
// - held by the OP itself in storage -> `openIDKeySet`
@ -39,20 +45,38 @@ func GetKeyIDAndAlg(jws *jose.JSONWebSignature) (string, string) {
//will return the key immediately if matches exact (id, usage, type)
//
//will return false none or multiple match
//
//deprecated: use FindMatchingKey which will return an error (more specific) instead of just a bool
//moved implementation already to FindMatchingKey
func FindKey(keyID, use, expectedAlg string, keys ...jose.JSONWebKey) (jose.JSONWebKey, bool) {
key, err := FindMatchingKey(keyID, use, expectedAlg, keys...)
return key, err == nil
}
//FindMatchingKey searches the given JSON Web Keys for the requested key ID, usage and key type
//
//will return the key immediately if matches exact (id, usage, type)
//
//will return a specific error if none (ErrKeyNone) or multiple (ErrKeyMultiple) match
func FindMatchingKey(keyID, use, expectedAlg string, keys ...jose.JSONWebKey) (key jose.JSONWebKey, err error) {
var validKeys []jose.JSONWebKey
for _, key := range keys {
if key.KeyID == keyID && key.Use == use && algToKeyType(key.Key, expectedAlg) {
if keyID != "" {
return key, true
for _, k := range keys {
if k.Use == use && algToKeyType(k.Key, expectedAlg) {
if k.KeyID == keyID && keyID != "" {
return k, nil
}
if k.KeyID == "" || keyID == "" {
validKeys = append(validKeys, k)
}
validKeys = append(validKeys, key)
}
}
if len(validKeys) == 1 {
return validKeys[0], true
return validKeys[0], nil
}
return jose.JSONWebKey{}, false
if len(validKeys) > 1 {
return key, ErrKeyMultiple
}
return key, ErrKeyNone
}
func algToKeyType(key interface{}, alg string) bool {