Files
Max KotliarandGitHub 94b32be80a lib/jwt: opensource jwt library (#10426)
### Describe Your Changes

It was
[decided](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9439#issuecomment-3612299461)
that OIDC authentication in vmauth will be part of open source repo.

That requires opensourcing lib/jwt. PR does not contain any changes in
logic, just copy-paste from enterprise repository.

Related to
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9439

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
- [ ] My change adheres to [VictoriaMetrics development
goals](https://docs.victoriametrics.com/victoriametrics/goals/).
2026-02-10 18:49:23 +02:00

105 lines
1.8 KiB
Go

package jwt
import (
"crypto"
"crypto/ecdsa"
"math/big"
)
// newVerifierES returns a new ECDSA-based verifier.
func newVerifierES(alg Algorithm, key *ecdsa.PublicKey) (*esAlg, error) {
if key == nil {
return nil, ErrNilKey
}
hash, err := getParamsES(alg, roundBytes(key.Params().BitSize)*2)
if err != nil {
return nil, err
}
return &esAlg{
alg: alg,
hash: hash,
publicKey: key,
signSize: signSize(key),
}, nil
}
func signSize(key *ecdsa.PublicKey) int {
return roundBytes(key.Params().BitSize) * 2
}
func getAlgorithmForKey(key *ecdsa.PublicKey) Algorithm {
switch signSize(key) {
case 64:
return ES256
case 96:
return ES384
case 132:
return ES512
}
return ""
}
func getParamsES(alg Algorithm, size int) (crypto.Hash, error) {
var hash crypto.Hash
var keySize int
switch alg {
case ES256:
hash, keySize = crypto.SHA256, 64
case ES384:
hash, keySize = crypto.SHA384, 96
case ES512:
hash, keySize = crypto.SHA512, 132
default:
return 0, ErrUnsupportedAlg
}
if keySize != size {
return 0, ErrInvalidKey
}
return hash, nil
}
type esAlg struct {
alg Algorithm
hash crypto.Hash
publicKey *ecdsa.PublicKey
signSize int
}
func (es *esAlg) SignSize() int {
return es.signSize
}
func (es *esAlg) Verify(token *Token) error {
return es.verify(token.payload, token.signature)
}
func (es *esAlg) verify(payload, signature []byte) error {
if len(signature) != es.SignSize() {
return ErrInvalidSignature
}
digest, err := hashPayload(es.hash, payload)
if err != nil {
return err
}
pivot := es.SignSize() / 2
r := big.NewInt(0).SetBytes(signature[:pivot])
s := big.NewInt(0).SetBytes(signature[pivot:])
if !ecdsa.Verify(es.publicKey, digest, r, s) {
return ErrInvalidSignature
}
return nil
}
func roundBytes(n int) int {
res := n / 8
if n%8 > 0 {
return res + 1
}
return res
}