Initial QSfera import

This commit is contained in:
Курнат Андрей
2026-06-07 10:20:04 +03:00
commit 2315f25754
16485 changed files with 4826827 additions and 0 deletions
+21
View File
@@ -0,0 +1,21 @@
load("@rules_go//go:def.bzl", "go_library")
go_library(
name = "legacy",
srcs = [
"ecdsa.go",
"eddsa.go",
"hmac.go",
"legacy.go",
"rsa.go",
],
importpath = "github.com/lestrrat-go/jwx/v3/jws/legacy",
visibility = ["//visibility:public"],
deps = [
"//internal/ecutil",
"//internal/keyconv",
"//internal/pool",
"//jwa",
"//jws/internal/keytype",
],
)
+204
View File
@@ -0,0 +1,204 @@
package legacy
import (
"crypto"
"crypto/ecdsa"
"crypto/rand"
"encoding/asn1"
"fmt"
"math/big"
"github.com/lestrrat-go/jwx/v3/internal/ecutil"
"github.com/lestrrat-go/jwx/v3/internal/keyconv"
"github.com/lestrrat-go/jwx/v3/internal/pool"
"github.com/lestrrat-go/jwx/v3/jwa"
"github.com/lestrrat-go/jwx/v3/jws/internal/keytype"
)
var ecdsaSigners = make(map[jwa.SignatureAlgorithm]*ecdsaSigner)
var ecdsaVerifiers = make(map[jwa.SignatureAlgorithm]*ecdsaVerifier)
func init() {
algs := map[jwa.SignatureAlgorithm]crypto.Hash{
jwa.ES256(): crypto.SHA256,
jwa.ES384(): crypto.SHA384,
jwa.ES512(): crypto.SHA512,
jwa.ES256K(): crypto.SHA256,
}
for alg, hash := range algs {
ecdsaSigners[alg] = &ecdsaSigner{
alg: alg,
hash: hash,
}
ecdsaVerifiers[alg] = &ecdsaVerifier{
alg: alg,
hash: hash,
}
}
}
func NewECDSASigner(alg jwa.SignatureAlgorithm) Signer {
return ecdsaSigners[alg]
}
// ecdsaSigners are immutable.
type ecdsaSigner struct {
alg jwa.SignatureAlgorithm
hash crypto.Hash
}
func (es ecdsaSigner) Algorithm() jwa.SignatureAlgorithm {
return es.alg
}
func (es *ecdsaSigner) Sign(payload []byte, key any) ([]byte, error) {
if key == nil {
return nil, fmt.Errorf(`missing private key while signing payload`)
}
h := es.hash.New()
if _, err := h.Write(payload); err != nil {
return nil, fmt.Errorf(`failed to write payload using ecdsa: %w`, err)
}
signer, ok := key.(crypto.Signer)
if ok {
if !keytype.IsValidECDSAKey(key) {
return nil, fmt.Errorf(`cannot use key of type %T to generate ECDSA based signatures`, key)
}
switch key.(type) {
case ecdsa.PrivateKey, *ecdsa.PrivateKey:
// if it's a ecdsa.PrivateKey, it's more efficient to
// go through the non-crypto.Signer route. Set ok to false
ok = false
}
}
var r, s *big.Int
var curveBits int
if ok {
signed, err := signer.Sign(rand.Reader, h.Sum(nil), es.hash)
if err != nil {
return nil, err
}
var p struct {
R *big.Int
S *big.Int
}
if _, err := asn1.Unmarshal(signed, &p); err != nil {
return nil, fmt.Errorf(`failed to unmarshal ASN1 encoded signature: %w`, err)
}
// Okay, this is silly, but hear me out. When we use the
// crypto.Signer interface, the PrivateKey is hidden.
// But we need some information about the key (its bit size).
//
// So while silly, we're going to have to make another call
// here and fetch the Public key.
// This probably means that this should be cached some where.
cpub := signer.Public()
pubkey, ok := cpub.(*ecdsa.PublicKey)
if !ok {
return nil, fmt.Errorf(`expected *ecdsa.PublicKey, got %T`, pubkey)
}
curveBits = pubkey.Curve.Params().BitSize
r = p.R
s = p.S
} else {
var privkey ecdsa.PrivateKey
if err := keyconv.ECDSAPrivateKey(&privkey, key); err != nil {
return nil, fmt.Errorf(`failed to retrieve ecdsa.PrivateKey out of %T: %w`, key, err)
}
curveBits = privkey.Curve.Params().BitSize
rtmp, stmp, err := ecdsa.Sign(rand.Reader, &privkey, h.Sum(nil))
if err != nil {
return nil, fmt.Errorf(`failed to sign payload using ecdsa: %w`, err)
}
r = rtmp
s = stmp
}
keyBytes := curveBits / 8
// Curve bits do not need to be a multiple of 8.
if curveBits%8 > 0 {
keyBytes++
}
rBytes := r.Bytes()
rBytesPadded := make([]byte, keyBytes)
copy(rBytesPadded[keyBytes-len(rBytes):], rBytes)
sBytes := s.Bytes()
sBytesPadded := make([]byte, keyBytes)
copy(sBytesPadded[keyBytes-len(sBytes):], sBytes)
out := append(rBytesPadded, sBytesPadded...)
return out, nil
}
// ecdsaVerifiers are immutable.
type ecdsaVerifier struct {
alg jwa.SignatureAlgorithm
hash crypto.Hash
}
func NewECDSAVerifier(alg jwa.SignatureAlgorithm) Verifier {
return ecdsaVerifiers[alg]
}
func (v ecdsaVerifier) Algorithm() jwa.SignatureAlgorithm {
return v.alg
}
func (v *ecdsaVerifier) Verify(payload []byte, signature []byte, key any) error {
if key == nil {
return fmt.Errorf(`missing public key while verifying payload`)
}
var pubkey ecdsa.PublicKey
if cs, ok := key.(crypto.Signer); ok {
cpub := cs.Public()
switch cpub := cpub.(type) {
case ecdsa.PublicKey:
pubkey = cpub
case *ecdsa.PublicKey:
pubkey = *cpub
default:
return fmt.Errorf(`failed to retrieve ecdsa.PublicKey out of crypto.Signer %T`, key)
}
} else {
if err := keyconv.ECDSAPublicKey(&pubkey, key); err != nil {
return fmt.Errorf(`failed to retrieve ecdsa.PublicKey out of %T: %w`, key, err)
}
}
if !pubkey.Curve.IsOnCurve(pubkey.X, pubkey.Y) {
return fmt.Errorf(`public key used does not contain a point (X,Y) on the curve`)
}
r := pool.BigInt().Get()
s := pool.BigInt().Get()
defer pool.BigInt().Put(r)
defer pool.BigInt().Put(s)
keySize := ecutil.CalculateKeySize(pubkey.Curve)
if len(signature) != keySize*2 {
return fmt.Errorf(`invalid signature length for curve %q`, pubkey.Curve.Params().Name)
}
r.SetBytes(signature[:keySize])
s.SetBytes(signature[keySize:])
h := v.hash.New()
if _, err := h.Write(payload); err != nil {
return fmt.Errorf(`failed to write payload using ecdsa: %w`, err)
}
if !ecdsa.Verify(&pubkey, h.Sum(nil), r, s) {
return fmt.Errorf(`failed to verify signature using ecdsa`)
}
return nil
}
+79
View File
@@ -0,0 +1,79 @@
package legacy
import (
"crypto"
"crypto/ed25519"
"crypto/rand"
"fmt"
"github.com/lestrrat-go/jwx/v3/internal/keyconv"
"github.com/lestrrat-go/jwx/v3/jwa"
"github.com/lestrrat-go/jwx/v3/jws/internal/keytype"
)
type eddsaSigner struct{}
func NewEdDSASigner() Signer {
return &eddsaSigner{}
}
func (s eddsaSigner) Algorithm() jwa.SignatureAlgorithm {
return jwa.EdDSA()
}
func (s eddsaSigner) Sign(payload []byte, key any) ([]byte, error) {
if key == nil {
return nil, fmt.Errorf(`missing private key while signing payload`)
}
// The ed25519.PrivateKey object implements crypto.Signer, so we should
// simply accept a crypto.Signer here.
signer, ok := key.(crypto.Signer)
if ok {
if !keytype.IsValidEDDSAKey(key) {
return nil, fmt.Errorf(`cannot use key of type %T to generate EdDSA based signatures`, key)
}
} else {
// This fallback exists for cases when jwk.Key was passed, or
// users gave us a pointer instead of non-pointer, etc.
var privkey ed25519.PrivateKey
if err := keyconv.Ed25519PrivateKey(&privkey, key); err != nil {
return nil, fmt.Errorf(`failed to retrieve ed25519.PrivateKey out of %T: %w`, key, err)
}
signer = privkey
}
return signer.Sign(rand.Reader, payload, crypto.Hash(0))
}
type eddsaVerifier struct{}
func NewEdDSAVerifier() Verifier {
return &eddsaVerifier{}
}
func (v eddsaVerifier) Verify(payload, signature []byte, key any) (err error) {
if key == nil {
return fmt.Errorf(`missing public key while verifying payload`)
}
var pubkey ed25519.PublicKey
signer, ok := key.(crypto.Signer)
if ok {
v := signer.Public()
pubkey, ok = v.(ed25519.PublicKey)
if !ok {
return fmt.Errorf(`expected crypto.Signer.Public() to return ed25519.PublicKey, but got %T`, v)
}
} else {
if err := keyconv.Ed25519PublicKey(&pubkey, key); err != nil {
return fmt.Errorf(`failed to retrieve ed25519.PublicKey out of %T: %w`, key, err)
}
}
if !ed25519.Verify(pubkey, payload, signature) {
return fmt.Errorf(`failed to match EdDSA signature`)
}
return nil
}
+90
View File
@@ -0,0 +1,90 @@
package legacy
import (
"crypto/hmac"
"crypto/sha256"
"crypto/sha512"
"fmt"
"hash"
"github.com/lestrrat-go/jwx/v3/internal/keyconv"
"github.com/lestrrat-go/jwx/v3/jwa"
)
func init() {
algs := map[jwa.SignatureAlgorithm]func() hash.Hash{
jwa.HS256(): sha256.New,
jwa.HS384(): sha512.New384,
jwa.HS512(): sha512.New,
}
for alg, h := range algs {
hmacSignFuncs[alg] = makeHMACSignFunc(h)
}
}
// HMACSigner uses crypto/hmac to sign the payloads.
// This is for legacy support only.
type HMACSigner struct {
alg jwa.SignatureAlgorithm
sign hmacSignFunc
}
type HMACVerifier struct {
signer Signer
}
type hmacSignFunc func(payload []byte, key []byte) ([]byte, error)
var hmacSignFuncs = make(map[jwa.SignatureAlgorithm]hmacSignFunc)
func NewHMACSigner(alg jwa.SignatureAlgorithm) Signer {
return &HMACSigner{
alg: alg,
sign: hmacSignFuncs[alg], // we know this will succeed
}
}
func makeHMACSignFunc(hfunc func() hash.Hash) hmacSignFunc {
return func(payload []byte, key []byte) ([]byte, error) {
h := hmac.New(hfunc, key)
if _, err := h.Write(payload); err != nil {
return nil, fmt.Errorf(`failed to write payload using hmac: %w`, err)
}
return h.Sum(nil), nil
}
}
func (s HMACSigner) Algorithm() jwa.SignatureAlgorithm {
return s.alg
}
func (s HMACSigner) Sign(payload []byte, key any) ([]byte, error) {
var hmackey []byte
if err := keyconv.ByteSliceKey(&hmackey, key); err != nil {
return nil, fmt.Errorf(`invalid key type %T. []byte is required: %w`, key, err)
}
if len(hmackey) == 0 {
return nil, fmt.Errorf(`missing key while signing payload`)
}
return s.sign(payload, hmackey)
}
func NewHMACVerifier(alg jwa.SignatureAlgorithm) Verifier {
s := NewHMACSigner(alg)
return &HMACVerifier{signer: s}
}
func (v HMACVerifier) Verify(payload, signature []byte, key any) (err error) {
expected, err := v.signer.Sign(payload, key)
if err != nil {
return fmt.Errorf(`failed to generated signature: %w`, err)
}
if !hmac.Equal(signature, expected) {
return fmt.Errorf(`failed to match hmac signature`)
}
return nil
}
+36
View File
@@ -0,0 +1,36 @@
// Package legacy provides support for legacy implementation of JWS signing and verification.
// Types, functions, and variables in this package are exported only for legacy support,
// and should not be relied upon for new code.
//
// This package will be available until v3 is sunset, but it will be removed in v4
package legacy
import (
"github.com/lestrrat-go/jwx/v3/jwa"
)
// Signer generates the signature for a given payload.
// This is for legacy support only.
type Signer interface {
// Sign creates a signature for the given payload.
// The second argument is the key used for signing the payload, and is usually
// the private key type associated with the signature method. For example,
// for `jwa.RSXXX` and `jwa.PSXXX` types, you need to pass the
// `*"crypto/rsa".PrivateKey` type.
// Check the documentation for each signer for details
Sign([]byte, any) ([]byte, error)
Algorithm() jwa.SignatureAlgorithm
}
// Verifier is for legacy support only.
type Verifier interface {
// Verify checks whether the payload and signature are valid for
// the given key.
// `key` is the key used for verifying the payload, and is usually
// the public key associated with the signature method. For example,
// for `jwa.RSXXX` and `jwa.PSXXX` types, you need to pass the
// `*"crypto/rsa".PublicKey` type.
// Check the documentation for each verifier for details
Verify(payload []byte, signature []byte, key any) error
}
+145
View File
@@ -0,0 +1,145 @@
package legacy
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"fmt"
"github.com/lestrrat-go/jwx/v3/internal/keyconv"
"github.com/lestrrat-go/jwx/v3/jwa"
"github.com/lestrrat-go/jwx/v3/jws/internal/keytype"
)
var rsaSigners = make(map[jwa.SignatureAlgorithm]*rsaSigner)
var rsaVerifiers = make(map[jwa.SignatureAlgorithm]*rsaVerifier)
func init() {
data := map[jwa.SignatureAlgorithm]struct {
Hash crypto.Hash
PSS bool
}{
jwa.RS256(): {
Hash: crypto.SHA256,
},
jwa.RS384(): {
Hash: crypto.SHA384,
},
jwa.RS512(): {
Hash: crypto.SHA512,
},
jwa.PS256(): {
Hash: crypto.SHA256,
PSS: true,
},
jwa.PS384(): {
Hash: crypto.SHA384,
PSS: true,
},
jwa.PS512(): {
Hash: crypto.SHA512,
PSS: true,
},
}
for alg, item := range data {
rsaSigners[alg] = &rsaSigner{
alg: alg,
hash: item.Hash,
pss: item.PSS,
}
rsaVerifiers[alg] = &rsaVerifier{
alg: alg,
hash: item.Hash,
pss: item.PSS,
}
}
}
type rsaSigner struct {
alg jwa.SignatureAlgorithm
hash crypto.Hash
pss bool
}
func NewRSASigner(alg jwa.SignatureAlgorithm) Signer {
return rsaSigners[alg]
}
func (rs *rsaSigner) Algorithm() jwa.SignatureAlgorithm {
return rs.alg
}
func (rs *rsaSigner) Sign(payload []byte, key any) ([]byte, error) {
if key == nil {
return nil, fmt.Errorf(`missing private key while signing payload`)
}
signer, ok := key.(crypto.Signer)
if ok {
if !keytype.IsValidRSAKey(key) {
return nil, fmt.Errorf(`cannot use key of type %T to generate RSA based signatures`, key)
}
} else {
var privkey rsa.PrivateKey
if err := keyconv.RSAPrivateKey(&privkey, key); err != nil {
return nil, fmt.Errorf(`failed to retrieve rsa.PrivateKey out of %T: %w`, key, err)
}
signer = &privkey
}
h := rs.hash.New()
if _, err := h.Write(payload); err != nil {
return nil, fmt.Errorf(`failed to write payload to hash: %w`, err)
}
if rs.pss {
return signer.Sign(rand.Reader, h.Sum(nil), &rsa.PSSOptions{
Hash: rs.hash,
SaltLength: rsa.PSSSaltLengthEqualsHash,
})
}
return signer.Sign(rand.Reader, h.Sum(nil), rs.hash)
}
type rsaVerifier struct {
alg jwa.SignatureAlgorithm
hash crypto.Hash
pss bool
}
func NewRSAVerifier(alg jwa.SignatureAlgorithm) Verifier {
return rsaVerifiers[alg]
}
func (rv *rsaVerifier) Verify(payload, signature []byte, key any) error {
if key == nil {
return fmt.Errorf(`missing public key while verifying payload`)
}
var pubkey rsa.PublicKey
if cs, ok := key.(crypto.Signer); ok {
cpub := cs.Public()
switch cpub := cpub.(type) {
case rsa.PublicKey:
pubkey = cpub
case *rsa.PublicKey:
pubkey = *cpub
default:
return fmt.Errorf(`failed to retrieve rsa.PublicKey out of crypto.Signer %T`, key)
}
} else {
if err := keyconv.RSAPublicKey(&pubkey, key); err != nil {
return fmt.Errorf(`failed to retrieve rsa.PublicKey out of %T: %w`, key, err)
}
}
h := rv.hash.New()
if _, err := h.Write(payload); err != nil {
return fmt.Errorf(`failed to write payload to hash: %w`, err)
}
if rv.pss {
return rsa.VerifyPSS(&pubkey, rv.hash, h.Sum(nil), signature, nil)
}
return rsa.VerifyPKCS1v15(&pubkey, rv.hash, h.Sum(nil), signature)
}