Browse Source
* Forcibly update the vendored versions using a replace Signed-off-by: Andrew Thornton <art27@cantab.net>tags/v1.14.6
13 changed files with 349 additions and 86 deletions
@ -1,11 +0,0 @@ |
|||||||
language: go |
|
||||||
|
|
||||||
script: |
|
||||||
- go vet ./... |
|
||||||
- go test -v ./... |
|
||||||
|
|
||||||
go: |
|
||||||
- 1.7 |
|
||||||
- 1.8 |
|
||||||
- 1.9 |
|
||||||
- 1.10 |
|
@ -0,0 +1,99 @@ |
|||||||
|
//+build !go1.15
|
||||||
|
|
||||||
|
package jwt |
||||||
|
|
||||||
|
import ( |
||||||
|
"crypto/ecdsa" |
||||||
|
"crypto/rand" |
||||||
|
"math/big" |
||||||
|
"math/bits" |
||||||
|
) |
||||||
|
|
||||||
|
// 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) |
||||||
|
fillBytesInt(r, out[0:keyBytes]) // r is assigned to the first half of output.
|
||||||
|
fillBytesInt(s, out[keyBytes:]) // s is assigned to the second half of output.
|
||||||
|
|
||||||
|
return EncodeSegment(out), nil |
||||||
|
} else { |
||||||
|
return "", err |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func fillBytesInt(x *big.Int, buf []byte) []byte { |
||||||
|
// Clear whole buffer. (This gets optimized into a memclr.)
|
||||||
|
for i := range buf { |
||||||
|
buf[i] = 0 |
||||||
|
} |
||||||
|
|
||||||
|
// This code is deeply inspired by go's own implementation but rewritten.
|
||||||
|
|
||||||
|
// Although this function is called bits it returns words
|
||||||
|
words := x.Bits() |
||||||
|
|
||||||
|
// Words are uints as per the definition of bits.Word and thus there are usually (64) /8 bytes per word
|
||||||
|
bytesPerWord := bits.UintSize / 8 |
||||||
|
|
||||||
|
// If our buffer is longer than the expected number of words start mid-way
|
||||||
|
pos := len(buf) - len(words)*bytesPerWord |
||||||
|
|
||||||
|
// Now iterate across the words (backwards)
|
||||||
|
for i := range words { |
||||||
|
// Grab the last word (Which is the biggest number)
|
||||||
|
word := words[len(words)-1-i] |
||||||
|
|
||||||
|
// Now for each byte in the word
|
||||||
|
// [abcd...] we want buf[0] = a, buf[1] = b ...
|
||||||
|
|
||||||
|
for j := bytesPerWord; j > 0; j-- { |
||||||
|
d := byte(word) |
||||||
|
// if our position is less than 0 then panic
|
||||||
|
if pos+j-1 >= 0 { |
||||||
|
// set the value of the byte to the byte
|
||||||
|
buf[pos+j-1] = d |
||||||
|
} else if d != 0 { |
||||||
|
panic("math/big: buffer too small to fit value") // have to use the same panic string for complete compatibility
|
||||||
|
} |
||||||
|
// shift the word 8 bits and reloop.
|
||||||
|
word >>= 8 |
||||||
|
} |
||||||
|
pos += bytesPerWord |
||||||
|
} |
||||||
|
|
||||||
|
return buf |
||||||
|
} |
@ -0,0 +1,54 @@ |
|||||||
|
//+build go1.15
|
||||||
|
|
||||||
|
package jwt |
||||||
|
|
||||||
|
import ( |
||||||
|
"crypto/ecdsa" |
||||||
|
"crypto/rand" |
||||||
|
) |
||||||
|
|
||||||
|
// 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 |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,81 @@ |
|||||||
|
package jwt |
||||||
|
|
||||||
|
import ( |
||||||
|
"errors" |
||||||
|
|
||||||
|
"crypto/ed25519" |
||||||
|
) |
||||||
|
|
||||||
|
var ( |
||||||
|
ErrEd25519Verification = errors.New("ed25519: verification error") |
||||||
|
) |
||||||
|
|
||||||
|
// Implements the EdDSA family
|
||||||
|
// Expects ed25519.PrivateKey for signing and ed25519.PublicKey for verification
|
||||||
|
type SigningMethodEd25519 struct{} |
||||||
|
|
||||||
|
// Specific instance for EdDSA
|
||||||
|
var ( |
||||||
|
SigningMethodEdDSA *SigningMethodEd25519 |
||||||
|
) |
||||||
|
|
||||||
|
func init() { |
||||||
|
SigningMethodEdDSA = &SigningMethodEd25519{} |
||||||
|
RegisterSigningMethod(SigningMethodEdDSA.Alg(), func() SigningMethod { |
||||||
|
return SigningMethodEdDSA |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
func (m *SigningMethodEd25519) Alg() string { |
||||||
|
return "EdDSA" |
||||||
|
} |
||||||
|
|
||||||
|
// Implements the Verify method from SigningMethod
|
||||||
|
// For this verify method, key must be an ed25519.PublicKey
|
||||||
|
func (m *SigningMethodEd25519) Verify(signingString, signature string, key interface{}) error { |
||||||
|
var err error |
||||||
|
var ed25519Key ed25519.PublicKey |
||||||
|
var ok bool |
||||||
|
|
||||||
|
if ed25519Key, ok = key.(ed25519.PublicKey); !ok { |
||||||
|
return ErrInvalidKeyType |
||||||
|
} |
||||||
|
|
||||||
|
if len(ed25519Key) != ed25519.PublicKeySize { |
||||||
|
return ErrInvalidKey |
||||||
|
} |
||||||
|
|
||||||
|
// Decode the signature
|
||||||
|
var sig []byte |
||||||
|
if sig, err = DecodeSegment(signature); err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
|
||||||
|
// Verify the signature
|
||||||
|
if !ed25519.Verify(ed25519Key, []byte(signingString), sig) { |
||||||
|
return ErrEd25519Verification |
||||||
|
} |
||||||
|
|
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
// Implements the Sign method from SigningMethod
|
||||||
|
// For this signing method, key must be an ed25519.PrivateKey
|
||||||
|
func (m *SigningMethodEd25519) Sign(signingString string, key interface{}) (string, error) { |
||||||
|
var ed25519Key ed25519.PrivateKey |
||||||
|
var ok bool |
||||||
|
|
||||||
|
if ed25519Key, ok = key.(ed25519.PrivateKey); !ok { |
||||||
|
return "", ErrInvalidKeyType |
||||||
|
} |
||||||
|
|
||||||
|
// ed25519.Sign panics if private key not equal to ed25519.PrivateKeySize
|
||||||
|
// this allows to avoid recover usage
|
||||||
|
if len(ed25519Key) != ed25519.PrivateKeySize { |
||||||
|
return "", ErrInvalidKey |
||||||
|
} |
||||||
|
|
||||||
|
// Sign the string and return the encoded result
|
||||||
|
sig := ed25519.Sign(ed25519Key, []byte(signingString)) |
||||||
|
return EncodeSegment(sig), nil |
||||||
|
} |
@ -0,0 +1,64 @@ |
|||||||
|
package jwt |
||||||
|
|
||||||
|
import ( |
||||||
|
"crypto" |
||||||
|
"crypto/ed25519" |
||||||
|
"crypto/x509" |
||||||
|
"encoding/pem" |
||||||
|
"errors" |
||||||
|
) |
||||||
|
|
||||||
|
var ( |
||||||
|
ErrNotEdPrivateKey = errors.New("Key is not a valid Ed25519 private key") |
||||||
|
ErrNotEdPublicKey = errors.New("Key is not a valid Ed25519 public key") |
||||||
|
) |
||||||
|
|
||||||
|
// Parse PEM-encoded Edwards curve private key
|
||||||
|
func ParseEdPrivateKeyFromPEM(key []byte) (crypto.PrivateKey, error) { |
||||||
|
var err error |
||||||
|
|
||||||
|
// Parse PEM block
|
||||||
|
var block *pem.Block |
||||||
|
if block, _ = pem.Decode(key); block == nil { |
||||||
|
return nil, ErrKeyMustBePEMEncoded |
||||||
|
} |
||||||
|
|
||||||
|
// Parse the key
|
||||||
|
var parsedKey interface{} |
||||||
|
if parsedKey, err = x509.ParsePKCS8PrivateKey(block.Bytes); err != nil { |
||||||
|
return nil, err |
||||||
|
} |
||||||
|
|
||||||
|
var pkey ed25519.PrivateKey |
||||||
|
var ok bool |
||||||
|
if pkey, ok = parsedKey.(ed25519.PrivateKey); !ok { |
||||||
|
return nil, ErrNotEdPrivateKey |
||||||
|
} |
||||||
|
|
||||||
|
return pkey, nil |
||||||
|
} |
||||||
|
|
||||||
|
// Parse PEM-encoded Edwards curve public key
|
||||||
|
func ParseEdPublicKeyFromPEM(key []byte) (crypto.PublicKey, error) { |
||||||
|
var err error |
||||||
|
|
||||||
|
// Parse PEM block
|
||||||
|
var block *pem.Block |
||||||
|
if block, _ = pem.Decode(key); block == nil { |
||||||
|
return nil, ErrKeyMustBePEMEncoded |
||||||
|
} |
||||||
|
|
||||||
|
// Parse the key
|
||||||
|
var parsedKey interface{} |
||||||
|
if parsedKey, err = x509.ParsePKIXPublicKey(block.Bytes); err != nil { |
||||||
|
return nil, err |
||||||
|
} |
||||||
|
|
||||||
|
var pkey ed25519.PublicKey |
||||||
|
var ok bool |
||||||
|
if pkey, ok = parsedKey.(ed25519.PublicKey); !ok { |
||||||
|
return nil, ErrNotEdPublicKey |
||||||
|
} |
||||||
|
|
||||||
|
return pkey, nil |
||||||
|
} |
Loading…
Reference in new issue