mirror of https://github.com/golang-jwt/jwt.git
added signing support to RS256 and HS256
This commit is contained in:
parent
af74bdc9d2
commit
d736b8f860
26
jwt.go
26
jwt.go
|
@ -18,6 +18,28 @@ type Token struct {
|
|||
Valid bool
|
||||
}
|
||||
|
||||
func New(method SigningMethod)*Token {
|
||||
return &Token{
|
||||
Header: map[string]interface{}{
|
||||
"typ": "JWT",
|
||||
"alg": method.Alg(),
|
||||
},
|
||||
Claims: make(map[string]interface{}),
|
||||
}
|
||||
}
|
||||
|
||||
func Sign(key []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func SigningString()string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func String()string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Parse, validate, and return a token.
|
||||
// keyFunc will receive the parsed token and should return the key for validating.
|
||||
// If everything is kosher, err will be nil
|
||||
|
@ -91,6 +113,10 @@ func ParseFromRequest(req *http.Request, keyFunc func(*Token) ([]byte, error)) (
|
|||
|
||||
}
|
||||
|
||||
func EncodeSegment(seg []byte)string {
|
||||
return strings.TrimRight(base64.URLEncoding.EncodeToString(seg), "=")
|
||||
}
|
||||
|
||||
func DecodeSegment(seg string) ([]byte, error) {
|
||||
// len % 4
|
||||
switch len(seg) % 4 {
|
||||
|
|
37
rs256.go
37
rs256.go
|
@ -5,6 +5,7 @@ import (
|
|||
"crypto/rsa"
|
||||
"crypto/sha256"
|
||||
"crypto/x509"
|
||||
"crypto/rand"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
)
|
||||
|
@ -17,6 +18,10 @@ func init() {
|
|||
})
|
||||
}
|
||||
|
||||
func (m *SigningMethodRS256) Alg()string {
|
||||
return "RS256"
|
||||
}
|
||||
|
||||
func (m *SigningMethodRS256) Verify(signingString, signature string, key []byte) (err error) {
|
||||
// Key
|
||||
var sig []byte
|
||||
|
@ -41,6 +46,34 @@ func (m *SigningMethodRS256) Verify(signingString, signature string, key []byte)
|
|||
return
|
||||
}
|
||||
|
||||
func (m *SigningMethodRS256) Sign(token *Token, key []byte) error {
|
||||
return nil
|
||||
func (m *SigningMethodRS256) Sign(signingString string, key []byte)(sig string, err error) {
|
||||
// Key
|
||||
var rsaKey *rsa.PrivateKey
|
||||
if rsaKey, err = m.parsePrivateKey(key); err == nil {
|
||||
hasher := sha256.New()
|
||||
hasher.Write([]byte(signingString))
|
||||
|
||||
var sigBytes []byte
|
||||
if sigBytes, err = rsa.SignPKCS1v15(rand.Reader, rsaKey, crypto.SHA256, hasher.Sum(nil)); err == nil {
|
||||
sig = EncodeSegment(sigBytes)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (m *SigningMethodRS256) parsePrivateKey(key []byte)(pkey *rsa.PrivateKey, err error) {
|
||||
var block *pem.Block
|
||||
if block, _ = pem.Decode(key); block != nil {
|
||||
var parsedKey interface{}
|
||||
if parsedKey, err = x509.ParsePKCS1PrivateKey(block.Bytes); err != nil {
|
||||
if parsedKey, err = x509.ParsePKCS8PrivateKey(block.Bytes); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
var ok bool
|
||||
if pkey, ok = parsedKey.(*rsa.PrivateKey); !ok {
|
||||
err = errors.New("Key is not a valid RSA private key")
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
|
@ -48,3 +48,26 @@ func TestRS256Verify(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func TestRS256Sign(t *testing.T) {
|
||||
file, _ := os.Open("test/sample_key")
|
||||
buf := new(bytes.Buffer)
|
||||
io.Copy(buf, file)
|
||||
key := buf.Bytes()
|
||||
file.Close()
|
||||
|
||||
for _, data := range rsaTestData {
|
||||
if data.valid {
|
||||
parts := strings.Split(data.tokenString, ".")
|
||||
method, _ := GetSigningMethod("RS256")
|
||||
sig, err := method.Sign(strings.Join(parts[0:2], "."), key)
|
||||
if err != nil {
|
||||
t.Errorf("[%v] Error signing token: %v", data.name, err)
|
||||
}
|
||||
if sig != parts[2] {
|
||||
t.Errorf("[%v] Incorrect signature.\nwas:\n%v\nexpecting:\n%v", data.name, sig, parts[2])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
sha256.go
11
sha256.go
|
@ -15,6 +15,10 @@ func init() {
|
|||
})
|
||||
}
|
||||
|
||||
func (m *SigningMethodHS256) Alg()string {
|
||||
return "HS256"
|
||||
}
|
||||
|
||||
func (m *SigningMethodHS256) Verify(signingString, signature string, key []byte) (err error) {
|
||||
// Key
|
||||
var sig []byte
|
||||
|
@ -29,6 +33,9 @@ func (m *SigningMethodHS256) Verify(signingString, signature string, key []byte)
|
|||
return
|
||||
}
|
||||
|
||||
func (m *SigningMethodHS256) Sign(token *Token, key []byte) error {
|
||||
return nil
|
||||
func (m *SigningMethodHS256) Sign(signingString string, key []byte)(string, error) {
|
||||
hasher := hmac.New(sha256.New, key)
|
||||
hasher.Write([]byte(signingString))
|
||||
|
||||
return EncodeSegment(hasher.Sum(nil)), nil
|
||||
}
|
||||
|
|
|
@ -46,3 +46,19 @@ func TestHS256Verify(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestHS256Sign(t *testing.T) {
|
||||
for _, data := range sha256TestData {
|
||||
if data.valid {
|
||||
parts := strings.Split(data.tokenString, ".")
|
||||
method, _ := GetSigningMethod("HS256")
|
||||
sig, err := method.Sign(strings.Join(parts[0:2], "."), sha256TestKey)
|
||||
if err != nil {
|
||||
t.Errorf("[%v] Error signing token: %v", data.name, err)
|
||||
}
|
||||
if sig != parts[2] {
|
||||
t.Errorf("[%v] Incorrect signature.\nwas:\n%v\nexpecting:\n%v", data.name, sig, parts[2])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,7 +10,8 @@ var signingMethods = map[string]func() SigningMethod{}
|
|||
// Signing method
|
||||
type SigningMethod interface {
|
||||
Verify(signingString, signature string, key []byte) error
|
||||
Sign(token *Token, key []byte) error
|
||||
Sign(signingString string, key []byte)(string, error)
|
||||
Alg() string
|
||||
}
|
||||
|
||||
func RegisterSigningMethod(alg string, f func() SigningMethod) {
|
||||
|
|
Loading…
Reference in New Issue