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