mirror of https://github.com/golang-jwt/jwt.git
Merge branch 'master' of github.com:dgrijalva/jwt-go
This commit is contained in:
commit
9a00cd52d4
|
@ -3,3 +3,5 @@ language: go
|
||||||
go:
|
go:
|
||||||
- 1.3.3
|
- 1.3.3
|
||||||
- 1.4.2
|
- 1.4.2
|
||||||
|
- 1.5
|
||||||
|
- tip
|
||||||
|
|
|
@ -48,6 +48,12 @@ Parsing and verifying tokens is pretty straight forward. You pass in the token
|
||||||
tokenString, err := token.SignedString(mySigningKey)
|
tokenString, err := token.SignedString(mySigningKey)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Extensions
|
||||||
|
|
||||||
|
This library publishes all the necessary components for adding your own signing methods. Simply implement the `SigningMethod` interface and register a factory method using `RegisterSigningMethod`.
|
||||||
|
|
||||||
|
Here's an example of an extension that integrates with the Google App Engine signing tools: https://github.com/someone1/gcp-jwt-go
|
||||||
|
|
||||||
## Project Status & Versioning
|
## Project Status & Versioning
|
||||||
|
|
||||||
This library is considered production ready. Feedback and feature requests are appreciated. The API should be considered stable. There should be very few backwards-incompatible changes outside of major version updates (and only with good reason).
|
This library is considered production ready. Feedback and feature requests are appreciated. The API should be considered stable. There should be very few backwards-incompatible changes outside of major version updates (and only with good reason).
|
||||||
|
|
57
ecdsa.go
57
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"
|
||||||
)
|
)
|
||||||
|
@ -18,12 +17,8 @@ var (
|
||||||
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,
|
||||||
|
|
|
@ -69,7 +69,7 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the Verify method from SigningMethod
|
// Implements the Verify method from SigningMethod
|
||||||
// For this verify method, key must be an rsa.PrivateKey struct
|
// For this verify method, key must be an rsa.PublicKey struct
|
||||||
func (m *SigningMethodRSAPSS) Verify(signingString, signature string, key interface{}) error {
|
func (m *SigningMethodRSAPSS) Verify(signingString, signature string, key interface{}) error {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
@ -98,7 +98,7 @@ func (m *SigningMethodRSAPSS) Verify(signingString, signature string, key interf
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the Sign method from SigningMethod
|
// Implements the Sign method from SigningMethod
|
||||||
// For this signing method, key must be an rsa.PublicKey struct
|
// For this signing method, key must be an rsa.PrivateKey struct
|
||||||
func (m *SigningMethodRSAPSS) Sign(signingString string, key interface{}) (string, error) {
|
func (m *SigningMethodRSAPSS) Sign(signingString string, key interface{}) (string, error) {
|
||||||
var rsaKey *rsa.PrivateKey
|
var rsaKey *rsa.PrivateKey
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue