rsa_pss.go (3439B)
1 // +build go1.4 2 3 package jwt 4 5 import ( 6 "crypto" 7 "crypto/rand" 8 "crypto/rsa" 9 ) 10 11 // Implements the RSAPSS family of signing methods signing methods 12 type SigningMethodRSAPSS struct { 13 *SigningMethodRSA 14 Options *rsa.PSSOptions 15 // VerifyOptions is optional. If set overrides Options for rsa.VerifyPPS. 16 // Used to accept tokens signed with rsa.PSSSaltLengthAuto, what doesn't follow 17 // https://tools.ietf.org/html/rfc7518#section-3.5 but was used previously. 18 // See https://github.com/dgrijalva/jwt-go/issues/285#issuecomment-437451244 for details. 19 VerifyOptions *rsa.PSSOptions 20 } 21 22 // Specific instances for RS/PS and company. 23 var ( 24 SigningMethodPS256 *SigningMethodRSAPSS 25 SigningMethodPS384 *SigningMethodRSAPSS 26 SigningMethodPS512 *SigningMethodRSAPSS 27 ) 28 29 func init() { 30 // PS256 31 SigningMethodPS256 = &SigningMethodRSAPSS{ 32 SigningMethodRSA: &SigningMethodRSA{ 33 Name: "PS256", 34 Hash: crypto.SHA256, 35 }, 36 Options: &rsa.PSSOptions{ 37 SaltLength: rsa.PSSSaltLengthEqualsHash, 38 }, 39 VerifyOptions: &rsa.PSSOptions{ 40 SaltLength: rsa.PSSSaltLengthAuto, 41 }, 42 } 43 RegisterSigningMethod(SigningMethodPS256.Alg(), func() SigningMethod { 44 return SigningMethodPS256 45 }) 46 47 // PS384 48 SigningMethodPS384 = &SigningMethodRSAPSS{ 49 SigningMethodRSA: &SigningMethodRSA{ 50 Name: "PS384", 51 Hash: crypto.SHA384, 52 }, 53 Options: &rsa.PSSOptions{ 54 SaltLength: rsa.PSSSaltLengthEqualsHash, 55 }, 56 VerifyOptions: &rsa.PSSOptions{ 57 SaltLength: rsa.PSSSaltLengthAuto, 58 }, 59 } 60 RegisterSigningMethod(SigningMethodPS384.Alg(), func() SigningMethod { 61 return SigningMethodPS384 62 }) 63 64 // PS512 65 SigningMethodPS512 = &SigningMethodRSAPSS{ 66 SigningMethodRSA: &SigningMethodRSA{ 67 Name: "PS512", 68 Hash: crypto.SHA512, 69 }, 70 Options: &rsa.PSSOptions{ 71 SaltLength: rsa.PSSSaltLengthEqualsHash, 72 }, 73 VerifyOptions: &rsa.PSSOptions{ 74 SaltLength: rsa.PSSSaltLengthAuto, 75 }, 76 } 77 RegisterSigningMethod(SigningMethodPS512.Alg(), func() SigningMethod { 78 return SigningMethodPS512 79 }) 80 } 81 82 // Implements the Verify method from SigningMethod 83 // For this verify method, key must be an rsa.PublicKey struct 84 func (m *SigningMethodRSAPSS) Verify(signingString, signature string, key interface{}) error { 85 var err error 86 87 // Decode the signature 88 var sig []byte 89 if sig, err = DecodeSegment(signature); err != nil { 90 return err 91 } 92 93 var rsaKey *rsa.PublicKey 94 switch k := key.(type) { 95 case *rsa.PublicKey: 96 rsaKey = k 97 default: 98 return ErrInvalidKey 99 } 100 101 // Create hasher 102 if !m.Hash.Available() { 103 return ErrHashUnavailable 104 } 105 hasher := m.Hash.New() 106 hasher.Write([]byte(signingString)) 107 108 opts := m.Options 109 if m.VerifyOptions != nil { 110 opts = m.VerifyOptions 111 } 112 113 return rsa.VerifyPSS(rsaKey, m.Hash, hasher.Sum(nil), sig, opts) 114 } 115 116 // Implements the Sign method from SigningMethod 117 // For this signing method, key must be an rsa.PrivateKey struct 118 func (m *SigningMethodRSAPSS) Sign(signingString string, key interface{}) (string, error) { 119 var rsaKey *rsa.PrivateKey 120 121 switch k := key.(type) { 122 case *rsa.PrivateKey: 123 rsaKey = k 124 default: 125 return "", ErrInvalidKeyType 126 } 127 128 // Create the hasher 129 if !m.Hash.Available() { 130 return "", ErrHashUnavailable 131 } 132 133 hasher := m.Hash.New() 134 hasher.Write([]byte(signingString)) 135 136 // Sign the string and return the encoded bytes 137 if sigBytes, err := rsa.SignPSS(rand.Reader, rsaKey, m.Hash, hasher.Sum(nil), m.Options); err == nil { 138 return EncodeSegment(sigBytes), nil 139 } else { 140 return "", err 141 } 142 }