1 package jwt_test
2
3 import (
4 "bytes"
5 "crypto/rand"
6 "crypto/rsa"
7 "crypto/x509"
8 "encoding/pem"
9 "os"
10 "reflect"
11 "strings"
12 "testing"
13
14 "github.com/golang-jwt/jwt/v5"
15 )
16
17 var rsaTestData = []struct {
18 name string
19 tokenString string
20 alg string
21 valid bool
22 }{
23 {
24 "Basic RS256",
25 "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.FhkiHkoESI_cG3NPigFrxEk9Z60_oXrOT2vGm9Pn6RDgYNovYORQmmA0zs1AoAOf09ly2Nx2YAg6ABqAYga1AcMFkJljwxTT5fYphTuqpWdy4BELeSYJx5Ty2gmr8e7RonuUztrdD5WfPqLKMm1Ozp_T6zALpRmwTIW0QPnaBXaQD90FplAg46Iy1UlDKr-Eupy0i5SLch5Q-p2ZpaL_5fnTIUDlxC3pWhJTyx_71qDI-mAA_5lE_VdroOeflG56sSmDxopPEG3bFlSu1eowyBfxtu0_CuVd-M42RU75Zc4Gsj6uV77MBtbMrf4_7M_NUTSgoIF3fRqxrj0NzihIBg",
26 "RS256",
27 true,
28 },
29 {
30 "Basic RS384",
31 "eyJhbGciOiJSUzM4NCIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIifQ.W-jEzRfBigtCWsinvVVuldiuilzVdU5ty0MvpLaSaqK9PlAWWlDQ1VIQ_qSKzwL5IXaZkvZFJXT3yL3n7OUVu7zCNJzdwznbC8Z-b0z2lYvcklJYi2VOFRcGbJtXUqgjk2oGsiqUMUMOLP70TTefkpsgqDxbRh9CDUfpOJgW-dU7cmgaoswe3wjUAUi6B6G2YEaiuXC0XScQYSYVKIzgKXJV8Zw-7AN_DBUI4GkTpsvQ9fVVjZM9csQiEXhYekyrKu1nu_POpQonGd8yqkIyXPECNmmqH5jH4sFiF67XhD7_JpkvLziBpI-uh86evBUadmHhb9Otqw3uV3NTaXLzJw",
32 "RS384",
33 true,
34 },
35 {
36 "Basic RS512",
37 "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIifQ.zBlLlmRrUxx4SJPUbV37Q1joRcI9EW13grnKduK3wtYKmDXbgDpF1cZ6B-2Jsm5RB8REmMiLpGms-EjXhgnyh2TSHE-9W2gA_jvshegLWtwRVDX40ODSkTb7OVuaWgiy9y7llvcknFBTIg-FnVPVpXMmeV_pvwQyhaz1SSwSPrDyxEmksz1hq7YONXhXPpGaNbMMeDTNP_1oj8DZaqTIL9TwV8_1wb2Odt_Fy58Ke2RVFijsOLdnyEAjt2n9Mxihu9i3PhNBkkxa2GbnXBfq3kzvZ_xxGGopLdHhJjcGWXO-NiwI9_tiu14NRv4L2xC0ItD9Yz68v2ZIZEp_DuzwRQ",
38 "RS512",
39 true,
40 },
41 {
42 "basic invalid: foo => bar",
43 "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.EhkiHkoESI_cG3NPigFrxEk9Z60_oXrOT2vGm9Pn6RDgYNovYORQmmA0zs1AoAOf09ly2Nx2YAg6ABqAYga1AcMFkJljwxTT5fYphTuqpWdy4BELeSYJx5Ty2gmr8e7RonuUztrdD5WfPqLKMm1Ozp_T6zALpRmwTIW0QPnaBXaQD90FplAg46Iy1UlDKr-Eupy0i5SLch5Q-p2ZpaL_5fnTIUDlxC3pWhJTyx_71qDI-mAA_5lE_VdroOeflG56sSmDxopPEG3bFlSu1eowyBfxtu0_CuVd-M42RU75Zc4Gsj6uV77MBtbMrf4_7M_NUTSgoIF3fRqxrj0NzihIBg",
44 "RS256",
45 false,
46 },
47 }
48
49 func TestRSAVerify(t *testing.T) {
50 keyData, _ := os.ReadFile("test/sample_key.pub")
51 key, _ := jwt.ParseRSAPublicKeyFromPEM(keyData)
52
53 for _, data := range rsaTestData {
54 parts := strings.Split(data.tokenString, ".")
55
56 method := jwt.GetSigningMethod(data.alg)
57 err := method.Verify(strings.Join(parts[0:2], "."), decodeSegment(t, parts[2]), key)
58 if data.valid && err != nil {
59 t.Errorf("[%v] Error while verifying key: %v", data.name, err)
60 }
61 if !data.valid && err == nil {
62 t.Errorf("[%v] Invalid key passed validation", data.name)
63 }
64 }
65 }
66
67 func TestRSASign(t *testing.T) {
68 keyData, _ := os.ReadFile("test/sample_key")
69 key, _ := jwt.ParseRSAPrivateKeyFromPEM(keyData)
70
71 for _, data := range rsaTestData {
72 if data.valid {
73 parts := strings.Split(data.tokenString, ".")
74 method := jwt.GetSigningMethod(data.alg)
75 sig, err := method.Sign(strings.Join(parts[0:2], "."), key)
76 if err != nil {
77 t.Errorf("[%v] Error signing token: %v", data.name, err)
78 }
79 if !reflect.DeepEqual(sig, decodeSegment(t, parts[2])) {
80 t.Errorf("[%v] Incorrect signature.\nwas:\n%v\nexpecting:\n%v", data.name, sig, parts[2])
81 }
82 }
83 }
84 }
85
86 func TestRSAVerifyWithPreParsedPrivateKey(t *testing.T) {
87 key, _ := os.ReadFile("test/sample_key.pub")
88 parsedKey, err := jwt.ParseRSAPublicKeyFromPEM(key)
89 if err != nil {
90 t.Fatal(err)
91 }
92 testData := rsaTestData[0]
93 parts := strings.Split(testData.tokenString, ".")
94 err = jwt.SigningMethodRS256.Verify(strings.Join(parts[0:2], "."), decodeSegment(t, parts[2]), parsedKey)
95 if err != nil {
96 t.Errorf("[%v] Error while verifying key: %v", testData.name, err)
97 }
98 }
99
100 func TestRSAWithPreParsedPrivateKey(t *testing.T) {
101 key, _ := os.ReadFile("test/sample_key")
102 parsedKey, err := jwt.ParseRSAPrivateKeyFromPEM(key)
103 if err != nil {
104 t.Fatal(err)
105 }
106 testData := rsaTestData[0]
107 parts := strings.Split(testData.tokenString, ".")
108 sig, err := jwt.SigningMethodRS256.Sign(strings.Join(parts[0:2], "."), parsedKey)
109 if err != nil {
110 t.Errorf("[%v] Error signing token: %v", testData.name, err)
111 }
112 if !reflect.DeepEqual(sig, decodeSegment(t, parts[2])) {
113 t.Errorf("[%v] Incorrect signature.\nwas:\n%v\nexpecting:\n%v", testData.name, sig, parts[2])
114 }
115 }
116
117 func TestRSAKeyParsing(t *testing.T) {
118 key, _ := os.ReadFile("test/sample_key")
119 secureKey, _ := os.ReadFile("test/privateSecure.pem")
120 pubKey, _ := os.ReadFile("test/sample_key.pub")
121 badKey := []byte("All your base are belong to key")
122
123 randomKey, err := rsa.GenerateKey(rand.Reader, 2048)
124 if err != nil {
125 t.Errorf("Failed to generate RSA private key: %v", err)
126 }
127
128 publicKeyBytes := x509.MarshalPKCS1PublicKey(&randomKey.PublicKey)
129 pkcs1Buffer := new(bytes.Buffer)
130 if err = pem.Encode(pkcs1Buffer, &pem.Block{Type: "RSA PUBLIC KEY", Bytes: publicKeyBytes}); err != nil {
131 t.Errorf("Failed to encode public pem: %v", err)
132 }
133
134
135 if _, e := jwt.ParseRSAPrivateKeyFromPEM(key); e != nil {
136 t.Errorf("Failed to parse valid private key: %v", e)
137 }
138
139 if k, e := jwt.ParseRSAPrivateKeyFromPEM(pubKey); e == nil {
140 t.Errorf("Parsed public key as valid private key: %v", k)
141 }
142
143 if k, e := jwt.ParseRSAPrivateKeyFromPEM(badKey); e == nil {
144 t.Errorf("Parsed invalid key as valid private key: %v", k)
145 }
146
147 if _, e := jwt.ParseRSAPrivateKeyFromPEMWithPassword(secureKey, "password"); e != nil {
148 t.Errorf("Failed to parse valid private key with password: %v", e)
149 }
150
151 if k, e := jwt.ParseRSAPrivateKeyFromPEMWithPassword(secureKey, "123132"); e == nil {
152 t.Errorf("Parsed private key with invalid password %v", k)
153 }
154
155
156 if _, e := jwt.ParseRSAPublicKeyFromPEM(pubKey); e != nil {
157 t.Errorf("Failed to parse valid public key: %v", e)
158 }
159
160 if k, e := jwt.ParseRSAPublicKeyFromPEM(key); e == nil {
161 t.Errorf("Parsed private key as valid public key: %v", k)
162 }
163
164 if k, e := jwt.ParseRSAPublicKeyFromPEM(badKey); e == nil {
165 t.Errorf("Parsed invalid key as valid private key: %v", k)
166 }
167
168 if _, err := jwt.ParseRSAPublicKeyFromPEM(pkcs1Buffer.Bytes()); err != nil {
169 t.Errorf("failed to parse RSA public key: %v", err)
170 }
171 }
172
173 func BenchmarkRSAParsing(b *testing.B) {
174 key, _ := os.ReadFile("test/sample_key")
175
176 b.ReportAllocs()
177 b.ResetTimer()
178 b.RunParallel(func(pb *testing.PB) {
179 for pb.Next() {
180 if _, err := jwt.ParseRSAPrivateKeyFromPEM(key); err != nil {
181 b.Fatalf("Unable to parse RSA private key: %v", err)
182 }
183 }
184 })
185 }
186
187 func BenchmarkRS256Signing(b *testing.B) {
188 key, _ := os.ReadFile("test/sample_key")
189 parsedKey, err := jwt.ParseRSAPrivateKeyFromPEM(key)
190 if err != nil {
191 b.Fatal(err)
192 }
193
194 benchmarkSigning(b, jwt.SigningMethodRS256, parsedKey)
195 }
196
197 func BenchmarkRS384Signing(b *testing.B) {
198 key, _ := os.ReadFile("test/sample_key")
199 parsedKey, err := jwt.ParseRSAPrivateKeyFromPEM(key)
200 if err != nil {
201 b.Fatal(err)
202 }
203
204 benchmarkSigning(b, jwt.SigningMethodRS384, parsedKey)
205 }
206
207 func BenchmarkRS512Signing(b *testing.B) {
208 key, _ := os.ReadFile("test/sample_key")
209 parsedKey, err := jwt.ParseRSAPrivateKeyFromPEM(key)
210 if err != nil {
211 b.Fatal(err)
212 }
213
214 benchmarkSigning(b, jwt.SigningMethodRS512, parsedKey)
215 }
216
View as plain text