35735bbef9
* Upgrade to golang-jwt 3.2.2 Upgrade to the latest version of golang-jwt Signed-off-by: Andrew Thornton <art27@cantab.net> * Forcibly replace the 3.2.1 version of golang-jwt/jwt and increase minimum Go version Using go.mod we can forcibly replace the 3.2.1 version used by goth to 3.2.2. Further given golang-jwt/jwts stated policy of only supporting supported go versions we should just raise our minimal version of go to 1.16 for 1.16 as by time of release 1.15 will be out of support. Signed-off-by: Andrew Thornton <art27@cantab.net> * update minimal go required Signed-off-by: Andrew Thornton <art27@cantab.net> * update config.yaml Signed-off-by: Andrew Thornton <art27@cantab.net> Co-authored-by: 6543 <6543@obermui.de>
142 lines
3.4 KiB
Go
Vendored
142 lines
3.4 KiB
Go
Vendored
package jwt
|
|
|
|
import (
|
|
"crypto"
|
|
"crypto/ecdsa"
|
|
"crypto/rand"
|
|
"errors"
|
|
"math/big"
|
|
)
|
|
|
|
var (
|
|
// Sadly this is missing from crypto/ecdsa compared to crypto/rsa
|
|
ErrECDSAVerification = errors.New("crypto/ecdsa: verification error")
|
|
)
|
|
|
|
// Implements the ECDSA family of signing methods signing methods
|
|
// Expects *ecdsa.PrivateKey for signing and *ecdsa.PublicKey for verification
|
|
type SigningMethodECDSA struct {
|
|
Name string
|
|
Hash crypto.Hash
|
|
KeySize int
|
|
CurveBits int
|
|
}
|
|
|
|
// Specific instances for EC256 and company
|
|
var (
|
|
SigningMethodES256 *SigningMethodECDSA
|
|
SigningMethodES384 *SigningMethodECDSA
|
|
SigningMethodES512 *SigningMethodECDSA
|
|
)
|
|
|
|
func init() {
|
|
// ES256
|
|
SigningMethodES256 = &SigningMethodECDSA{"ES256", crypto.SHA256, 32, 256}
|
|
RegisterSigningMethod(SigningMethodES256.Alg(), func() SigningMethod {
|
|
return SigningMethodES256
|
|
})
|
|
|
|
// ES384
|
|
SigningMethodES384 = &SigningMethodECDSA{"ES384", crypto.SHA384, 48, 384}
|
|
RegisterSigningMethod(SigningMethodES384.Alg(), func() SigningMethod {
|
|
return SigningMethodES384
|
|
})
|
|
|
|
// ES512
|
|
SigningMethodES512 = &SigningMethodECDSA{"ES512", crypto.SHA512, 66, 521}
|
|
RegisterSigningMethod(SigningMethodES512.Alg(), func() SigningMethod {
|
|
return SigningMethodES512
|
|
})
|
|
}
|
|
|
|
func (m *SigningMethodECDSA) Alg() string {
|
|
return m.Name
|
|
}
|
|
|
|
// Implements the Verify method from SigningMethod
|
|
// For this verify method, key must be an ecdsa.PublicKey struct
|
|
func (m *SigningMethodECDSA) Verify(signingString, signature string, key interface{}) error {
|
|
var err error
|
|
|
|
// Decode the signature
|
|
var sig []byte
|
|
if sig, err = DecodeSegment(signature); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Get the key
|
|
var ecdsaKey *ecdsa.PublicKey
|
|
switch k := key.(type) {
|
|
case *ecdsa.PublicKey:
|
|
ecdsaKey = k
|
|
default:
|
|
return ErrInvalidKeyType
|
|
}
|
|
|
|
if len(sig) != 2*m.KeySize {
|
|
return ErrECDSAVerification
|
|
}
|
|
|
|
r := big.NewInt(0).SetBytes(sig[:m.KeySize])
|
|
s := big.NewInt(0).SetBytes(sig[m.KeySize:])
|
|
|
|
// Create hasher
|
|
if !m.Hash.Available() {
|
|
return ErrHashUnavailable
|
|
}
|
|
hasher := m.Hash.New()
|
|
hasher.Write([]byte(signingString))
|
|
|
|
// Verify the signature
|
|
if verifystatus := ecdsa.Verify(ecdsaKey, hasher.Sum(nil), r, s); verifystatus {
|
|
return nil
|
|
}
|
|
|
|
return ErrECDSAVerification
|
|
}
|
|
|
|
// Implements the Sign method from SigningMethod
|
|
// For this signing method, key must be an ecdsa.PrivateKey struct
|
|
func (m *SigningMethodECDSA) Sign(signingString string, key interface{}) (string, error) {
|
|
// Get the key
|
|
var ecdsaKey *ecdsa.PrivateKey
|
|
switch k := key.(type) {
|
|
case *ecdsa.PrivateKey:
|
|
ecdsaKey = k
|
|
default:
|
|
return "", ErrInvalidKeyType
|
|
}
|
|
|
|
// Create the hasher
|
|
if !m.Hash.Available() {
|
|
return "", ErrHashUnavailable
|
|
}
|
|
|
|
hasher := m.Hash.New()
|
|
hasher.Write([]byte(signingString))
|
|
|
|
// Sign the string and return r, s
|
|
if r, s, err := ecdsa.Sign(rand.Reader, ecdsaKey, hasher.Sum(nil)); err == nil {
|
|
curveBits := ecdsaKey.Curve.Params().BitSize
|
|
|
|
if m.CurveBits != curveBits {
|
|
return "", ErrInvalidKey
|
|
}
|
|
|
|
keyBytes := curveBits / 8
|
|
if curveBits%8 > 0 {
|
|
keyBytes += 1
|
|
}
|
|
|
|
// We serialize the outputs (r and s) into big-endian byte arrays
|
|
// padded with zeros on the left to make sure the sizes work out.
|
|
// Output must be 2*keyBytes long.
|
|
out := make([]byte, 2*keyBytes)
|
|
r.FillBytes(out[0:keyBytes]) // r is assigned to the first half of output.
|
|
s.FillBytes(out[keyBytes:]) // s is assigned to the second half of output.
|
|
|
|
return EncodeSegment(out), nil
|
|
} else {
|
|
return "", err
|
|
}
|
|
}
|