blob: 10ee9db8a4ed65e118f8f6611b7f47c0b0e0512f [file] [log] [blame]
khenaidooffe076b2019-01-15 16:08:08 -05001// +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}