Merge branch 'master' of github.com:dgrijalva/jwt-go

This commit is contained in:
Dave Grijalva 2015-10-29 11:26:19 -07:00
commit 9a00cd52d4
5 changed files with 49 additions and 30 deletions

View File

@ -3,3 +3,5 @@ language: go
go: go:
- 1.3.3 - 1.3.3
- 1.4.2 - 1.4.2
- 1.5
- tip

View File

@ -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).

View File

@ -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
} }

View File

@ -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,

View File

@ -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