1// +build go1.4 2 3package jwt 4 5import ( 6 "crypto" 7 "crypto/rand" 8 "crypto/rsa" 9) 10 11// Implements the RSAPSS family of signing methods signing methods 12type SigningMethodRSAPSS struct { 13 *SigningMethodRSA 14 Options *rsa.PSSOptions 15} 16 17// Specific instances for RS/PS and company 18var ( 19 SigningMethodPS256 *SigningMethodRSAPSS 20 SigningMethodPS384 *SigningMethodRSAPSS 21 SigningMethodPS512 *SigningMethodRSAPSS 22) 23 24func init() { 25 // PS256 26 SigningMethodPS256 = &SigningMethodRSAPSS{ 27 &SigningMethodRSA{ 28 Name: "PS256", 29 Hash: crypto.SHA256, 30 }, 31 &rsa.PSSOptions{ 32 SaltLength: rsa.PSSSaltLengthAuto, 33 Hash: crypto.SHA256, 34 }, 35 } 36 RegisterSigningMethod(SigningMethodPS256.Alg(), func() SigningMethod { 37 return SigningMethodPS256 38 }) 39 40 // PS384 41 SigningMethodPS384 = &SigningMethodRSAPSS{ 42 &SigningMethodRSA{ 43 Name: "PS384", 44 Hash: crypto.SHA384, 45 }, 46 &rsa.PSSOptions{ 47 SaltLength: rsa.PSSSaltLengthAuto, 48 Hash: crypto.SHA384, 49 }, 50 } 51 RegisterSigningMethod(SigningMethodPS384.Alg(), func() SigningMethod { 52 return SigningMethodPS384 53 }) 54 55 // PS512 56 SigningMethodPS512 = &SigningMethodRSAPSS{ 57 &SigningMethodRSA{ 58 Name: "PS512", 59 Hash: crypto.SHA512, 60 }, 61 &rsa.PSSOptions{ 62 SaltLength: rsa.PSSSaltLengthAuto, 63 Hash: crypto.SHA512, 64 }, 65 } 66 RegisterSigningMethod(SigningMethodPS512.Alg(), func() SigningMethod { 67 return SigningMethodPS512 68 }) 69} 70 71// Implements the Verify method from SigningMethod 72// For this verify method, key must be an rsa.PublicKey struct 73func (m *SigningMethodRSAPSS) Verify(signingString, signature string, key interface{}) error { 74 var err error 75 76 // Decode the signature 77 var sig []byte 78 if sig, err = DecodeSegment(signature); err != nil { 79 return err 80 } 81 82 var rsaKey *rsa.PublicKey 83 switch k := key.(type) { 84 case *rsa.PublicKey: 85 rsaKey = k 86 default: 87 return ErrInvalidKey 88 } 89 90 // Create hasher 91 if !m.Hash.Available() { 92 return ErrHashUnavailable 93 } 94 hasher := m.Hash.New() 95 hasher.Write([]byte(signingString)) 96 97 return rsa.VerifyPSS(rsaKey, m.Hash, hasher.Sum(nil), sig, m.Options) 98} 99 100// Implements the Sign method from SigningMethod 101// For this signing method, key must be an rsa.PrivateKey struct 102func (m *SigningMethodRSAPSS) Sign(signingString string, key interface{}) (string, error) { 103 var rsaKey *rsa.PrivateKey 104 105 switch k := key.(type) { 106 case *rsa.PrivateKey: 107 rsaKey = k 108 default: 109 return "", ErrInvalidKeyType 110 } 111 112 // Create the hasher 113 if !m.Hash.Available() { 114 return "", ErrHashUnavailable 115 } 116 117 hasher := m.Hash.New() 118 hasher.Write([]byte(signingString)) 119 120 // Sign the string and return the encoded bytes 121 if sigBytes, err := rsa.SignPSS(rand.Reader, rsaKey, m.Hash, hasher.Sum(nil), m.Options); err == nil { 122 return EncodeSegment(sigBytes), nil 123 } else { 124 return "", err 125 } 126} 127