Files
QSfera/Server/vendor/github.com/lestrrat-go/jwx/v3/jws/verifier.go
T
Курнат Андрей 2315f25754 Initial QSfera import
2026-06-07 10:20:04 +03:00

155 lines
4.4 KiB
Go

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)
}