| // +build go1.4 |
| |
| package jwt |
| |
| import ( |
| "crypto" |
| "crypto/rand" |
| "crypto/rsa" |
| ) |
| |
| // Implements the RSAPSS family of signing methods signing methods |
| type SigningMethodRSAPSS struct { |
| *SigningMethodRSA |
| Options *rsa.PSSOptions |
| } |
| |
| // Specific instances for RS/PS and company |
| var ( |
| SigningMethodPS256 *SigningMethodRSAPSS |
| SigningMethodPS384 *SigningMethodRSAPSS |
| SigningMethodPS512 *SigningMethodRSAPSS |
| ) |
| |
| func init() { |
| // PS256 |
| SigningMethodPS256 = &SigningMethodRSAPSS{ |
| &SigningMethodRSA{ |
| Name: "PS256", |
| Hash: crypto.SHA256, |
| }, |
| &rsa.PSSOptions{ |
| SaltLength: rsa.PSSSaltLengthAuto, |
| Hash: crypto.SHA256, |
| }, |
| } |
| RegisterSigningMethod(SigningMethodPS256.Alg(), func() SigningMethod { |
| return SigningMethodPS256 |
| }) |
| |
| // PS384 |
| SigningMethodPS384 = &SigningMethodRSAPSS{ |
| &SigningMethodRSA{ |
| Name: "PS384", |
| Hash: crypto.SHA384, |
| }, |
| &rsa.PSSOptions{ |
| SaltLength: rsa.PSSSaltLengthAuto, |
| Hash: crypto.SHA384, |
| }, |
| } |
| RegisterSigningMethod(SigningMethodPS384.Alg(), func() SigningMethod { |
| return SigningMethodPS384 |
| }) |
| |
| // PS512 |
| SigningMethodPS512 = &SigningMethodRSAPSS{ |
| &SigningMethodRSA{ |
| Name: "PS512", |
| Hash: crypto.SHA512, |
| }, |
| &rsa.PSSOptions{ |
| SaltLength: rsa.PSSSaltLengthAuto, |
| Hash: crypto.SHA512, |
| }, |
| } |
| RegisterSigningMethod(SigningMethodPS512.Alg(), func() SigningMethod { |
| return SigningMethodPS512 |
| }) |
| } |
| |
| // Implements the Verify method from SigningMethod |
| // For this verify method, key must be an rsa.PublicKey struct |
| func (m *SigningMethodRSAPSS) Verify(signingString, signature string, key interface{}) error { |
| var err error |
| |
| // Decode the signature |
| var sig []byte |
| if sig, err = DecodeSegment(signature); err != nil { |
| return err |
| } |
| |
| var rsaKey *rsa.PublicKey |
| switch k := key.(type) { |
| case *rsa.PublicKey: |
| rsaKey = k |
| default: |
| return ErrInvalidKey |
| } |
| |
| // Create hasher |
| if !m.Hash.Available() { |
| return ErrHashUnavailable |
| } |
| hasher := m.Hash.New() |
| hasher.Write([]byte(signingString)) |
| |
| return rsa.VerifyPSS(rsaKey, m.Hash, hasher.Sum(nil), sig, m.Options) |
| } |
| |
| // Implements the Sign method from SigningMethod |
| // For this signing method, key must be an rsa.PrivateKey struct |
| func (m *SigningMethodRSAPSS) Sign(signingString string, key interface{}) (string, error) { |
| var rsaKey *rsa.PrivateKey |
| |
| switch k := key.(type) { |
| case *rsa.PrivateKey: |
| rsaKey = 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 the encoded bytes |
| if sigBytes, err := rsa.SignPSS(rand.Reader, rsaKey, m.Hash, hasher.Sum(nil), m.Options); err == nil { |
| return EncodeSegment(sigBytes), nil |
| } else { |
| return "", err |
| } |
| } |