mirror of https://github.com/golang-jwt/jwt.git
Merge pull request #87 from vektra/master
Fix ES signature serialization
This commit is contained in:
commit
f62f64ea22
61
ecdsa.go
61
ecdsa.go
|
@ -4,7 +4,6 @@ import (
|
||||||
"crypto"
|
"crypto"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/asn1"
|
|
||||||
"errors"
|
"errors"
|
||||||
"math/big"
|
"math/big"
|
||||||
)
|
)
|
||||||
|
@ -16,14 +15,10 @@ var (
|
||||||
|
|
||||||
// Implements the ECDSA family of signing methods signing methods
|
// Implements the ECDSA family of signing methods signing methods
|
||||||
type SigningMethodECDSA struct {
|
type SigningMethodECDSA struct {
|
||||||
Name string
|
Name string
|
||||||
Hash crypto.Hash
|
Hash crypto.Hash
|
||||||
}
|
KeySize int
|
||||||
|
CurveBits int
|
||||||
// Marshalling structure for r, s EC point
|
|
||||||
type ECPoint struct {
|
|
||||||
R *big.Int
|
|
||||||
S *big.Int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Specific instances for EC256 and company
|
// Specific instances for EC256 and company
|
||||||
|
@ -35,19 +30,19 @@ var (
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
// ES256
|
// ES256
|
||||||
SigningMethodES256 = &SigningMethodECDSA{"ES256", crypto.SHA256}
|
SigningMethodES256 = &SigningMethodECDSA{"ES256", crypto.SHA256, 32, 256}
|
||||||
RegisterSigningMethod(SigningMethodES256.Alg(), func() SigningMethod {
|
RegisterSigningMethod(SigningMethodES256.Alg(), func() SigningMethod {
|
||||||
return SigningMethodES256
|
return SigningMethodES256
|
||||||
})
|
})
|
||||||
|
|
||||||
// ES384
|
// ES384
|
||||||
SigningMethodES384 = &SigningMethodECDSA{"ES384", crypto.SHA384}
|
SigningMethodES384 = &SigningMethodECDSA{"ES384", crypto.SHA384, 48, 384}
|
||||||
RegisterSigningMethod(SigningMethodES384.Alg(), func() SigningMethod {
|
RegisterSigningMethod(SigningMethodES384.Alg(), func() SigningMethod {
|
||||||
return SigningMethodES384
|
return SigningMethodES384
|
||||||
})
|
})
|
||||||
|
|
||||||
// ES512
|
// ES512
|
||||||
SigningMethodES512 = &SigningMethodECDSA{"ES512", crypto.SHA512}
|
SigningMethodES512 = &SigningMethodECDSA{"ES512", crypto.SHA512, 66, 521}
|
||||||
RegisterSigningMethod(SigningMethodES512.Alg(), func() SigningMethod {
|
RegisterSigningMethod(SigningMethodES512.Alg(), func() SigningMethod {
|
||||||
return SigningMethodES512
|
return SigningMethodES512
|
||||||
})
|
})
|
||||||
|
@ -77,12 +72,13 @@ func (m *SigningMethodECDSA) Verify(signingString, signature string, key interfa
|
||||||
return ErrInvalidKey
|
return ErrInvalidKey
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unmarshal asn1 ECPoint
|
if len(sig) != 2*m.KeySize {
|
||||||
var ecpoint = new(ECPoint)
|
return ErrECDSAVerification
|
||||||
if _, err := asn1.Unmarshal(sig, ecpoint); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
r := big.NewInt(0).SetBytes(sig[:m.KeySize])
|
||||||
|
s := big.NewInt(0).SetBytes(sig[m.KeySize:])
|
||||||
|
|
||||||
// Create hasher
|
// Create hasher
|
||||||
if !m.Hash.Available() {
|
if !m.Hash.Available() {
|
||||||
return ErrHashUnavailable
|
return ErrHashUnavailable
|
||||||
|
@ -91,7 +87,7 @@ func (m *SigningMethodECDSA) Verify(signingString, signature string, key interfa
|
||||||
hasher.Write([]byte(signingString))
|
hasher.Write([]byte(signingString))
|
||||||
|
|
||||||
// Verify the signature
|
// Verify the signature
|
||||||
if verifystatus := ecdsa.Verify(ecdsaKey, hasher.Sum(nil), ecpoint.R, ecpoint.S); verifystatus == true {
|
if verifystatus := ecdsa.Verify(ecdsaKey, hasher.Sum(nil), r, s); verifystatus == true {
|
||||||
return nil
|
return nil
|
||||||
} else {
|
} else {
|
||||||
return ErrECDSAVerification
|
return ErrECDSAVerification
|
||||||
|
@ -120,16 +116,31 @@ func (m *SigningMethodECDSA) Sign(signingString string, key interface{}) (string
|
||||||
|
|
||||||
// Sign the string and return r, s
|
// Sign the string and return r, s
|
||||||
if r, s, err := ecdsa.Sign(rand.Reader, ecdsaKey, hasher.Sum(nil)); err == nil {
|
if r, s, err := ecdsa.Sign(rand.Reader, ecdsaKey, hasher.Sum(nil)); err == nil {
|
||||||
// asn1 marhsal r, s using ecPoint as the structure
|
curveBits := ecdsaKey.Curve.Params().BitSize
|
||||||
var ecpoint = new(ECPoint)
|
|
||||||
ecpoint.R = r
|
|
||||||
ecpoint.S = s
|
|
||||||
|
|
||||||
if signature, err := asn1.Marshal(*ecpoint); err != nil {
|
if m.CurveBits != curveBits {
|
||||||
return "", err
|
return "", ErrInvalidKey
|
||||||
} else {
|
|
||||||
return EncodeSegment(signature), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
keyBytes := curveBits / 8
|
||||||
|
if curveBits%8 > 0 {
|
||||||
|
keyBytes += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// We serialize the outpus (r and s) into big-endian byte arrays and pad
|
||||||
|
// them with zeros on the left to make sure the sizes work out. Both arrays
|
||||||
|
// must be keyBytes long, and the output must be 2*keyBytes long.
|
||||||
|
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 EncodeSegment(out), nil
|
||||||
} else {
|
} else {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ var ecdsaTestData = []struct {
|
||||||
{
|
{
|
||||||
"Basic ES256",
|
"Basic ES256",
|
||||||
map[string]string{"private": "test/ec256-private.pem", "public": "test/ec256-public.pem"},
|
map[string]string{"private": "test/ec256-private.pem", "public": "test/ec256-public.pem"},
|
||||||
"eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIifQ.MEQCIHoSJnmGlPaVQDqacx_2XlXEhhqtWceVopjomc2PJLtdAiAUTeGPoNYxZw0z8mgOnnIcjoxRuNDVZvybRZF3wR1l8w",
|
"eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJmb28iOiJiYXIifQ.feG39E-bn8HXAKhzDZq7yEAPWYDhZlwTn3sePJnU9VrGMmwdXAIEyoOnrjreYlVM_Z4N13eK9-TmMTWyfKJtHQ",
|
||||||
"ES256",
|
"ES256",
|
||||||
map[string]interface{}{"foo": "bar"},
|
map[string]interface{}{"foo": "bar"},
|
||||||
true,
|
true,
|
||||||
|
@ -28,7 +28,7 @@ var ecdsaTestData = []struct {
|
||||||
{
|
{
|
||||||
"Basic ES384",
|
"Basic ES384",
|
||||||
map[string]string{"private": "test/ec384-private.pem", "public": "test/ec384-public.pem"},
|
map[string]string{"private": "test/ec384-private.pem", "public": "test/ec384-public.pem"},
|
||||||
"eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIifQ.MGUCMQCHBr61FXDuFY9xUhyp8iWQAuBIaSgaf1z2j_8XrKcCfzTPzoSa3SZKq-m3L492xe8CMG3kafRMeuaN5Aw8ZJxmOLhkTo4D3-LaGzcaUWINvWvkwFMl7dMC863s0gov6xvXuA",
|
"eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzM4NCJ9.eyJmb28iOiJiYXIifQ.ngAfKMbJUh0WWubSIYe5GMsA-aHNKwFbJk_wq3lq23aPp8H2anb1rRILIzVR0gUf4a8WzDtrzmiikuPWyCS6CN4-PwdgTk-5nehC7JXqlaBZU05p3toM3nWCwm_LXcld",
|
||||||
"ES384",
|
"ES384",
|
||||||
map[string]interface{}{"foo": "bar"},
|
map[string]interface{}{"foo": "bar"},
|
||||||
true,
|
true,
|
||||||
|
@ -36,7 +36,7 @@ var ecdsaTestData = []struct {
|
||||||
{
|
{
|
||||||
"Basic ES512",
|
"Basic ES512",
|
||||||
map[string]string{"private": "test/ec512-private.pem", "public": "test/ec512-public.pem"},
|
map[string]string{"private": "test/ec512-private.pem", "public": "test/ec512-public.pem"},
|
||||||
"eyJhbGciOiJFUzUxMiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIifQ.MIGIAkIAmVKjdJE5lG1byOFgZZVTeNDRp6E7SNvUj0UrvpzoBH6nrleWVTcwfHzbwWuooNpPADDSFR_Ql3ze-Vwwi8hBqQsCQgHn-ZooL8zegkOVeEEsqd7WHWdhb8UekFCYw3X8JnNP-D3wvZQ1-tkkHakt5gZ2-xO29TxfSPun4ViGkMYa7Q4N-Q",
|
"eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzUxMiJ9.eyJmb28iOiJiYXIifQ.AAU0TvGQOcdg2OvrwY73NHKgfk26UDekh9Prz-L_iWuTBIBqOFCWwwLsRiHB1JOddfKAls5do1W0jR_F30JpVd-6AJeTjGKA4C1A1H6gIKwRY0o_tFDIydZCl_lMBMeG5VNFAjO86-WCSKwc3hqaGkq1MugPRq_qrF9AVbuEB4JPLyL5",
|
||||||
"ES512",
|
"ES512",
|
||||||
map[string]interface{}{"foo": "bar"},
|
map[string]interface{}{"foo": "bar"},
|
||||||
true,
|
true,
|
||||||
|
|
Loading…
Reference in New Issue