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