Initial QSfera import
This commit is contained in:
+154
@@ -0,0 +1,154 @@
|
||||
package jws
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/lestrrat-go/jwx/v3/jwa"
|
||||
"github.com/lestrrat-go/jwx/v3/jws/jwsbb"
|
||||
)
|
||||
|
||||
type defaultVerifier struct {
|
||||
alg jwa.SignatureAlgorithm
|
||||
}
|
||||
|
||||
func (v defaultVerifier) Algorithm() jwa.SignatureAlgorithm {
|
||||
return v.alg
|
||||
}
|
||||
|
||||
func (v defaultVerifier) Verify(key any, payload, signature []byte) error {
|
||||
if err := jwsbb.Verify(key, v.alg.String(), payload, signature); err != nil {
|
||||
return verifyError{verificationError{err}}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Verifier2 interface {
|
||||
Verify(key any, payload, signature []byte) error
|
||||
}
|
||||
|
||||
var muVerifier2DB sync.RWMutex
|
||||
var verifier2DB = make(map[jwa.SignatureAlgorithm]Verifier2)
|
||||
|
||||
type verifierAdapter struct {
|
||||
v Verifier
|
||||
}
|
||||
|
||||
func (v verifierAdapter) Verify(key any, payload, signature []byte) error {
|
||||
if err := v.v.Verify(payload, signature, key); err != nil {
|
||||
return verifyError{verificationError{err}}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// VerifierFor returns a Verifier2 for the given signature algorithm.
|
||||
//
|
||||
// Currently, this function will never fail. It will always return a
|
||||
// valid Verifier2 object. The heuristic is as follows:
|
||||
// 1. If a Verifier2 is registered for the given algorithm, it will return that.
|
||||
// 2. If a legacy Verifier(Factory) is registered for the given algorithm, it will
|
||||
// return a Verifier2 that wraps the legacy Verifier.
|
||||
// 3. If no Verifier2 or legacy Verifier(Factory) is registered, it will return a
|
||||
// default verifier that uses jwsbb.Verify.
|
||||
//
|
||||
// jwsbb.Verify knows how to handle a static set of algorithms, so if the
|
||||
// algorithm is not supported, it will return an error when you call
|
||||
// `Verify` on the default verifier.
|
||||
func VerifierFor(alg jwa.SignatureAlgorithm) (Verifier2, error) {
|
||||
muVerifier2DB.RLock()
|
||||
defer muVerifier2DB.RUnlock()
|
||||
|
||||
v2, ok := verifier2DB[alg]
|
||||
if ok {
|
||||
return v2, nil
|
||||
}
|
||||
|
||||
v1, err := NewVerifier(alg)
|
||||
if err == nil {
|
||||
return verifierAdapter{v: v1}, nil
|
||||
}
|
||||
|
||||
return defaultVerifier{alg: alg}, nil
|
||||
}
|
||||
|
||||
type VerifierFactory interface {
|
||||
Create() (Verifier, error)
|
||||
}
|
||||
type VerifierFactoryFn func() (Verifier, error)
|
||||
|
||||
func (fn VerifierFactoryFn) Create() (Verifier, error) {
|
||||
return fn()
|
||||
}
|
||||
|
||||
var muVerifierDB sync.RWMutex
|
||||
var verifierDB = make(map[jwa.SignatureAlgorithm]VerifierFactory)
|
||||
|
||||
// RegisterVerifier is used to register a verifier for the given
|
||||
// algorithm.
|
||||
//
|
||||
// Please note that this function is intended to be passed a
|
||||
// verifier object as its second argument, but due to historical
|
||||
// reasons the function signature is defined as taking `any` type.
|
||||
//
|
||||
// You should create a signer object that implements the `Verifier2`
|
||||
// interface to register a signer, unless you have legacy code that
|
||||
// plugged into the `SignerFactory` interface.
|
||||
//
|
||||
// Unlike the `UnregisterVerifier` function, this function automatically
|
||||
// calls `jwa.RegisterSignatureAlgorithm` to register the algorithm
|
||||
// in this module's algorithm database.
|
||||
func RegisterVerifier(alg jwa.SignatureAlgorithm, f any) error {
|
||||
jwa.RegisterSignatureAlgorithm(alg)
|
||||
switch v := f.(type) {
|
||||
case Verifier2:
|
||||
muVerifier2DB.Lock()
|
||||
verifier2DB[alg] = v
|
||||
muVerifier2DB.Unlock()
|
||||
|
||||
muVerifierDB.Lock()
|
||||
delete(verifierDB, alg)
|
||||
muVerifierDB.Unlock()
|
||||
case VerifierFactory:
|
||||
muVerifierDB.Lock()
|
||||
verifierDB[alg] = v
|
||||
muVerifierDB.Unlock()
|
||||
|
||||
muVerifier2DB.Lock()
|
||||
delete(verifier2DB, alg)
|
||||
muVerifier2DB.Unlock()
|
||||
default:
|
||||
return fmt.Errorf(`jws.RegisterVerifier: unsupported type %T for algorithm %q`, f, alg)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnregisterVerifier removes the signer factory associated with
|
||||
// the given algorithm.
|
||||
//
|
||||
// Note that when you call this function, the algorithm itself is
|
||||
// not automatically unregistered from this module's algorithm database.
|
||||
// This is because the algorithm may still be required for signing or
|
||||
// some other operation (however unlikely, it is still possible).
|
||||
// Therefore, in order to completely remove the algorithm, you must
|
||||
// call `jwa.UnregisterSignatureAlgorithm` yourself.
|
||||
func UnregisterVerifier(alg jwa.SignatureAlgorithm) {
|
||||
muVerifier2DB.Lock()
|
||||
delete(verifier2DB, alg)
|
||||
muVerifier2DB.Unlock()
|
||||
|
||||
muVerifierDB.Lock()
|
||||
delete(verifierDB, alg)
|
||||
muVerifierDB.Unlock()
|
||||
}
|
||||
|
||||
// NewVerifier creates a verifier that signs payloads using the given signature algorithm.
|
||||
func NewVerifier(alg jwa.SignatureAlgorithm) (Verifier, error) {
|
||||
muVerifierDB.RLock()
|
||||
f, ok := verifierDB[alg]
|
||||
muVerifierDB.RUnlock()
|
||||
|
||||
if ok {
|
||||
return f.Create()
|
||||
}
|
||||
return nil, fmt.Errorf(`jws.NewVerifier: unsupported signature algorithm "%s"`, alg)
|
||||
}
|
||||
Reference in New Issue
Block a user