1 package jwk_test
2
3 import (
4 "bytes"
5 "context"
6 "crypto"
7 "crypto/ecdsa"
8 "crypto/ed25519"
9 "crypto/rsa"
10 "fmt"
11 "io"
12 "math/big"
13 "net/http"
14 "net/http/httptest"
15 "reflect"
16 "regexp"
17 "strconv"
18 "strings"
19 "testing"
20 "time"
21
22 "github.com/lestrrat-go/jwx/internal/ecutil"
23 "github.com/lestrrat-go/jwx/internal/jose"
24 "github.com/lestrrat-go/jwx/internal/json"
25 "github.com/lestrrat-go/jwx/internal/jwxtest"
26 "github.com/lestrrat-go/jwx/jws"
27 "github.com/pkg/errors"
28
29 "github.com/lestrrat-go/jwx/internal/base64"
30 "github.com/lestrrat-go/jwx/jwa"
31 "github.com/lestrrat-go/jwx/jwk"
32 "github.com/lestrrat-go/jwx/x25519"
33 "github.com/stretchr/testify/assert"
34 )
35
36 var zeroval reflect.Value
37 var certChainSrc = []string{
38 "MIIE3jCCA8agAwIBAgICAwEwDQYJKoZIhvcNAQEFBQAwYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMTYwMTU0MzdaFw0yNjExMTYwMTU0MzdaMIHKMQswCQYDVQQGEwJVUzEQMA4GA1UECBMHQXJpem9uYTETMBEGA1UEBxMKU2NvdHRzZGFsZTEaMBgGA1UEChMRR29EYWRkeS5jb20sIEluYy4xMzAxBgNVBAsTKmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9yeTEwMC4GA1UEAxMnR28gRGFkZHkgU2VjdXJlIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MREwDwYDVQQFEwgwNzk2OTI4NzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMQt1RWMnCZM7DI161+4WQFapmGBWTtwY6vj3D3HKrjJM9N55DrtPDAjhI6zMBS2sofDPZVUBJ7fmd0LJR4h3mUpfjWoqVTr9vcyOdQmVZWt7/v+WIbXnvQAjYwqDL1CBM6nPwT27oDyqu9SoWlm2r4arV3aLGbqGmu75RpRSgAvSMeYddi5Kcju+GZtCpyz8/x4fKL4o/K1w/O5epHBp+YlLpyo7RJlbmr2EkRTcDCVw5wrWCs9CHRK8r5RsL+H0EwnWGu1NcWdrxcx+AuP7q2BNgWJCJjPOq8lh8BJ6qf9Z/dFjpfMFDniNoW1fho3/Rb2cRGadDAW/hOUoz+EDU8CAwEAAaOCATIwggEuMB0GA1UdDgQWBBT9rGEyk2xF1uLuhV+auud2mWjM5zAfBgNVHSMEGDAWgBTSxLDSkdRMEXGzYcs9of7dqGrU4zASBgNVHRMBAf8ECDAGAQH/AgEAMDMGCCsGAQUFBwEBBCcwJTAjBggrBgEFBQcwAYYXaHR0cDovL29jc3AuZ29kYWRkeS5jb20wRgYDVR0fBD8wPTA7oDmgN4Y1aHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNvbS9yZXBvc2l0b3J5L2dkcm9vdC5jcmwwSwYDVR0gBEQwQjBABgRVHSAAMDgwNgYIKwYBBQUHAgEWKmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9yeTAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBANKGwOy9+aG2Z+5mC6IGOgRQjhVyrEp0lVPLN8tESe8HkGsz2ZbwlFalEzAFPIUyIXvJxwqoJKSQ3kbTJSMUA2fCENZvD117esyfxVgqwcSeIaha86ykRvOe5GPLL5CkKSkB2XIsKd83ASe8T+5o0yGPwLPk9Qnt0hCqU7S+8MxZC9Y7lhyVJEnfzuz9p0iRFEUOOjZv2kWzRaJBydTXRE4+uXR21aITVSzGh6O1mawGhId/dQb8vxRMDsxuxN89txJx9OjxUUAiKEngHUuHqDTMBqLdElrRhjZkAzVvb3du6/KFUJheqwNTrZEjYx8WnM25sgVjOuH0aBsXBTWVU+4=",
39 "MIIE+zCCBGSgAwIBAgICAQ0wDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTA0MDYyOTE3MDYyMFoXDTI0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjggHhMIIB3TAdBgNVHQ4EFgQU0sSw0pHUTBFxs2HLPaH+3ahq1OMwgdIGA1UdIwSByjCBx6GBwaSBvjCBuzEkMCIGA1UEBxMbVmFsaUNlcnQgVmFsaWRhdGlvbiBOZXR3b3JrMRcwFQYDVQQKEw5WYWxpQ2VydCwgSW5jLjE1MDMGA1UECxMsVmFsaUNlcnQgQ2xhc3MgMiBQb2xpY3kgVmFsaWRhdGlvbiBBdXRob3JpdHkxITAfBgNVBAMTGGh0dHA6Ly93d3cudmFsaWNlcnQuY29tLzEgMB4GCSqGSIb3DQEJARYRaW5mb0B2YWxpY2VydC5jb22CAQEwDwYDVR0TAQH/BAUwAwEB/zAzBggrBgEFBQcBAQQnMCUwIwYIKwYBBQUHMAGGF2h0dHA6Ly9vY3NwLmdvZGFkZHkuY29tMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9yeS9yb290LmNybDBLBgNVHSAERDBCMEAGBFUdIAAwODA2BggrBgEFBQcCARYqaHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNvbS9yZXBvc2l0b3J5MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOBgQC1QPmnHfbq/qQaQlpE9xXUhUaJwL6e4+PrxeNYiY+Sn1eocSxI0YGyeR+sBjUZsE4OWBsUs5iB0QQeyAfJg594RAoYC5jcdnplDQ1tgMQLARzLrUc+cb53S8wGd9D0VmsfSxOaFIqII6hR8INMqzW/Rn453HWkrugp++85j09VZw==",
40 "MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMTk1NFoXDTE5MDYyNjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vYdA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QSv4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9vUJSZSWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTuIYEZoDJJKPTEjlbVUjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwCW/POuZ6lcg5Ktz885hZo+L7tdEy8W9ViH0Pd",
41 }
42
43 type keyDef struct {
44 Expected interface{}
45 Value interface{}
46 Method string
47 }
48
49 var commonDef map[string]keyDef
50
51 func init() {
52 var certChain jwk.CertificateChain
53 certChain.Accept(certChainSrc)
54
55 commonDef = map[string]keyDef{
56 jwk.AlgorithmKey: {
57 Method: "Algorithm",
58 Value: "random-algorithm",
59 },
60 jwk.KeyIDKey: {
61 Method: "KeyID",
62 Value: "12312rdfsdfer2342342",
63 },
64 jwk.KeyUsageKey: {
65 Method: "KeyUsage",
66 Value: jwk.ForSignature,
67 Expected: string(jwk.ForSignature),
68 },
69 jwk.KeyOpsKey: {
70 Method: "KeyOps",
71 Value: jwk.KeyOperationList{
72 jwk.KeyOpSign,
73 jwk.KeyOpVerify,
74 jwk.KeyOpEncrypt,
75 jwk.KeyOpDecrypt,
76 jwk.KeyOpWrapKey,
77 jwk.KeyOpUnwrapKey,
78 jwk.KeyOpDeriveKey,
79 jwk.KeyOpDeriveBits,
80 },
81 },
82 jwk.X509CertChainKey: {
83 Method: "X509CertChain",
84 Value: certChainSrc,
85 Expected: certChain.Get(),
86 },
87 jwk.X509CertThumbprintKey: {
88 Value: "x5t blah",
89 Method: "X509CertThumbprint",
90 },
91 jwk.X509CertThumbprintS256Key: {
92 Value: "x5t#256 blah",
93 Method: "X509CertThumbprintS256",
94 },
95 jwk.X509URLKey: {
96 Value: "http://github.com/lestrrat-go/jwx",
97 Method: "X509URL",
98 },
99 "private": {Value: "boofoo"},
100 }
101 }
102
103 func complimentDef(def map[string]keyDef) map[string]keyDef {
104 for k, v := range commonDef {
105 if _, ok := def[k]; !ok {
106 def[k] = v
107 }
108 }
109 return def
110 }
111
112 func makeKeyJSON(def map[string]keyDef) []byte {
113 data := map[string]interface{}{}
114 for k, v := range def {
115 data[k] = v.Value
116 }
117 src, err := json.Marshal(data)
118 if err != nil {
119 panic(err)
120 }
121 return src
122 }
123
124 func expectBase64(kdef keyDef) keyDef {
125 v, err := base64.DecodeString(kdef.Value.(string))
126 if err != nil {
127 panic(err)
128 }
129 kdef.Expected = v
130 return kdef
131 }
132
133 func expectedRawKeyType(key jwk.Key) interface{} {
134 switch key := key.(type) {
135 case jwk.RSAPrivateKey:
136 return &rsa.PrivateKey{}
137 case jwk.RSAPublicKey:
138 return &rsa.PublicKey{}
139 case jwk.ECDSAPrivateKey:
140 return &ecdsa.PrivateKey{}
141 case jwk.ECDSAPublicKey:
142 return &ecdsa.PublicKey{}
143 case jwk.SymmetricKey:
144 return []byte(nil)
145 case jwk.OKPPrivateKey:
146 switch key.Crv() {
147 case jwa.Ed25519:
148 return ed25519.PrivateKey(nil)
149 case jwa.X25519:
150 return x25519.PrivateKey(nil)
151 default:
152 panic("unknown curve type for OKPPrivateKey:" + key.Crv())
153 }
154 case jwk.OKPPublicKey:
155 switch key.Crv() {
156 case jwa.Ed25519:
157 return ed25519.PublicKey(nil)
158 case jwa.X25519:
159 return x25519.PublicKey(nil)
160 default:
161 panic("unknown curve type for OKPPublicKey:" + key.Crv())
162 }
163 default:
164 panic("unknown key type:" + reflect.TypeOf(key).String())
165 }
166 }
167
168 func VerifyKey(t *testing.T, def map[string]keyDef) {
169 t.Helper()
170
171 def = complimentDef(def)
172 key, err := jwk.ParseKey(makeKeyJSON(def))
173 if !assert.NoError(t, err, `jwk.ParseKey should succeed`) {
174 return
175 }
176
177 t.Run("Fields", func(t *testing.T) {
178 for k, kdef := range def {
179 k := k
180 kdef := kdef
181 t.Run(k, func(t *testing.T) {
182 getval, ok := key.Get(k)
183 if !assert.True(t, ok, `key.Get(%s) should succeed`, k) {
184 return
185 }
186 expected := kdef.Expected
187 if expected == nil {
188 expected = kdef.Value
189 }
190 if !assert.Equal(t, expected, getval) {
191 return
192 }
193
194 if mname := kdef.Method; mname != "" {
195 method := reflect.ValueOf(key).MethodByName(mname)
196 if !assert.NotEqual(t, zeroval, method, `method should not be a zero value`) {
197 return
198 }
199 retvals := method.Call(nil)
200
201 if !assert.Len(t, retvals, 1, `there should be 1 return value`) {
202 return
203 }
204
205 if !assert.Equal(t, expected, retvals[0].Interface()) {
206 return
207 }
208 }
209 })
210 }
211 })
212 t.Run("Roundtrip", func(t *testing.T) {
213 buf, err := json.Marshal(key)
214 if !assert.NoError(t, err, `json.Marshal should succeed`) {
215 return
216 }
217
218 newkey, err := jwk.ParseKey(buf)
219 if !assert.NoError(t, err, `jwk.ParseKey should succeed`) {
220 return
221 }
222
223 m1, err := key.AsMap(context.TODO())
224 if !assert.NoError(t, err, `key.AsMap should succeed`) {
225 return
226 }
227
228 m2, err := newkey.AsMap(context.TODO())
229 if !assert.NoError(t, err, `key.AsMap should succeed`) {
230 return
231 }
232
233 if !assert.Equal(t, m1, m2, `keys should match`) {
234 return
235 }
236 })
237 t.Run("Raw", func(t *testing.T) {
238 typ := expectedRawKeyType(key)
239
240 var rawkey interface{}
241 if !assert.NoError(t, key.Raw(&rawkey), `Raw() should succeed`) {
242 return
243 }
244 if !assert.IsType(t, rawkey, typ, `raw key should be of this type`) {
245 return
246 }
247 })
248 t.Run("PublicKey", func(t *testing.T) {
249 _, err := jwk.PublicKeyOf(key)
250 if !assert.NoError(t, err, `jwk.PublicKeyOf should succeed`) {
251 return
252 }
253 })
254 t.Run("Set/Remove", func(t *testing.T) {
255 ctx := context.TODO()
256
257 newkey, err := key.Clone()
258 if !assert.NoError(t, err, `key.Clone should succeed`) {
259 return
260 }
261
262 for iter := key.Iterate(ctx); iter.Next(ctx); {
263 pair := iter.Pair()
264 newkey.Remove(pair.Key.(string))
265 }
266
267 m, err := newkey.AsMap(ctx)
268 if !assert.NoError(t, err, `key.AsMap should succeed`) {
269 return
270 }
271
272 if !assert.Len(t, m, 1, `keys should have 1 key (kty remains)`) {
273 return
274 }
275
276 for iter := key.Iterate(ctx); iter.Next(ctx); {
277 pair := iter.Pair()
278 if !assert.NoError(t, newkey.Set(pair.Key.(string), pair.Value), `newkey.Set should succeed`) {
279 return
280 }
281 }
282 })
283 }
284
285 func TestNew(t *testing.T) {
286 t.Parallel()
287 k, err := jwk.New(nil)
288 if !assert.Nil(t, k, "key should be nil") {
289 return
290 }
291 if !assert.Error(t, err, "nil key should cause an error") {
292 return
293 }
294 }
295
296 func TestParse(t *testing.T) {
297 t.Parallel()
298 verify := func(t *testing.T, src string, expected reflect.Type) {
299 t.Helper()
300 t.Run("json.Unmarshal", func(t *testing.T) {
301 set := jwk.NewSet()
302 if err := json.Unmarshal([]byte(src), set); !assert.NoError(t, err, `json.Unmarshal should succeed`) {
303 return
304 }
305
306 if !assert.True(t, set.Len() > 0, "set.Keys should be greater than 0") {
307 return
308 }
309
310 ctx, cancel := context.WithCancel(context.Background())
311 defer cancel()
312
313 for iter := set.Iterate(ctx); iter.Next(ctx); {
314 pair := iter.Pair()
315 if !assert.True(t, reflect.TypeOf(pair.Value).AssignableTo(expected), "key should be a %s", expected) {
316 return
317 }
318 }
319 })
320 t.Run("jwk.Parse", func(t *testing.T) {
321 t.Helper()
322 set, err := jwk.Parse([]byte(`{"keys":[` + src + `]}`))
323 if !assert.NoError(t, err, `jwk.Parse should succeed`) {
324 return
325 }
326
327 if !assert.True(t, set.Len() > 0, "set.Len should be greater than 0") {
328 return
329 }
330
331 for iter := set.Iterate(context.TODO()); iter.Next(context.TODO()); {
332 pair := iter.Pair()
333 key := pair.Value.(jwk.Key)
334
335 switch key := key.(type) {
336 case jwk.RSAPrivateKey, jwk.ECDSAPrivateKey, jwk.OKPPrivateKey, jwk.RSAPublicKey, jwk.ECDSAPublicKey, jwk.OKPPublicKey, jwk.SymmetricKey:
337 default:
338 assert.Fail(t, fmt.Sprintf("invalid type: %T", key))
339 }
340 }
341 })
342 t.Run("jwk.ParseKey", func(t *testing.T) {
343 t.Helper()
344 key, err := jwk.ParseKey([]byte(src))
345 if !assert.NoError(t, err, `jwk.ParseKey should succeed`) {
346 return
347 }
348
349 t.Run("Raw", func(t *testing.T) {
350 t.Helper()
351
352 var irawkey interface{}
353 if !assert.NoError(t, key.Raw(&irawkey), `key.Raw(&interface) should ucceed`) {
354 return
355 }
356
357 var crawkey interface{}
358 switch k := key.(type) {
359 case jwk.RSAPrivateKey:
360 var rawkey rsa.PrivateKey
361 if !assert.NoError(t, key.Raw(&rawkey), `key.Raw(&rsa.PrivateKey) should succeed`) {
362 return
363 }
364 crawkey = &rawkey
365 case jwk.RSAPublicKey:
366 var rawkey rsa.PublicKey
367 if !assert.NoError(t, key.Raw(&rawkey), `key.Raw(&rsa.PublicKey) should succeed`) {
368 return
369 }
370 crawkey = &rawkey
371 case jwk.ECDSAPrivateKey:
372 var rawkey ecdsa.PrivateKey
373 if !assert.NoError(t, key.Raw(&rawkey), `key.Raw(&ecdsa.PrivateKey) should succeed`) {
374 return
375 }
376 crawkey = &rawkey
377 case jwk.OKPPrivateKey:
378 switch k.Crv() {
379 case jwa.Ed25519:
380 var rawkey ed25519.PrivateKey
381 if !assert.NoError(t, key.Raw(&rawkey), `key.Raw(&ed25519.PrivateKey) should succeed`) {
382 return
383 }
384 crawkey = rawkey
385 case jwa.X25519:
386 var rawkey x25519.PrivateKey
387 if !assert.NoError(t, key.Raw(&rawkey), `key.Raw(&x25519.PrivateKey) should succeed`) {
388 return
389 }
390 crawkey = rawkey
391 default:
392 t.Errorf(`invalid curve %s`, k.Crv())
393 }
394
395
396
397 case jwk.OKPPublicKey:
398 switch k.Crv() {
399 case jwa.Ed25519:
400 var rawkey ed25519.PublicKey
401 if !assert.NoError(t, key.Raw(&rawkey), `key.Raw(&ed25519.PublicKey) should succeed`) {
402 return
403 }
404 crawkey = rawkey
405 case jwa.X25519:
406 var rawkey x25519.PublicKey
407 if !assert.NoError(t, key.Raw(&rawkey), `key.Raw(&x25519.PublicKey) should succeed`) {
408 return
409 }
410 crawkey = rawkey
411 default:
412 t.Errorf(`invalid curve %s`, k.Crv())
413 }
414 default:
415 t.Errorf(`invalid key type %T`, key)
416 return
417 }
418
419 if !assert.IsType(t, crawkey, irawkey, `key types should match`) {
420 return
421 }
422 })
423 })
424 t.Run("ParseRawKey", func(t *testing.T) {
425 var v interface{}
426 if !assert.NoError(t, jwk.ParseRawKey([]byte(src), &v), `jwk.ParseRawKey should succeed`) {
427 return
428 }
429 })
430 }
431
432 t.Run("RSA Public Key", func(t *testing.T) {
433 t.Parallel()
434 const src = `{
435 "e":"AQAB",
436 "kty":"RSA",
437 "n":"0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw"
438 }`
439 verify(t, src, reflect.TypeOf((*jwk.RSAPublicKey)(nil)).Elem())
440 })
441 t.Run("RSA Private Key", func(t *testing.T) {
442 t.Parallel()
443 const src = `{
444 "kty":"RSA",
445 "n":"0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
446 "e":"AQAB",
447 "d":"X4cTteJY_gn4FYPsXB8rdXix5vwsg1FLN5E3EaG6RJoVH-HLLKD9M7dx5oo7GURknchnrRweUkC7hT5fJLM0WbFAKNLWY2vv7B6NqXSzUvxT0_YSfqijwp3RTzlBaCxWp4doFk5N2o8Gy_nHNKroADIkJ46pRUohsXywbReAdYaMwFs9tv8d_cPVY3i07a3t8MN6TNwm0dSawm9v47UiCl3Sk5ZiG7xojPLu4sbg1U2jx4IBTNBznbJSzFHK66jT8bgkuqsk0GjskDJk19Z4qwjwbsnn4j2WBii3RL-Us2lGVkY8fkFzme1z0HbIkfz0Y6mqnOYtqc0X4jfcKoAC8Q",
448 "p":"83i-7IvMGXoMXCskv73TKr8637FiO7Z27zv8oj6pbWUQyLPQBQxtPVnwD20R-60eTDmD2ujnMt5PoqMrm8RfmNhVWDtjjMmCMjOpSXicFHj7XOuVIYQyqVWlWEh6dN36GVZYk93N8Bc9vY41xy8B9RzzOGVQzXvNEvn7O0nVbfs",
449 "q":"3dfOR9cuYq-0S-mkFLzgItgMEfFzB2q3hWehMuG0oCuqnb3vobLyumqjVZQO1dIrdwgTnCdpYzBcOfW5r370AFXjiWft_NGEiovonizhKpo9VVS78TzFgxkIdrecRezsZ-1kYd_s1qDbxtkDEgfAITAG9LUnADun4vIcb6yelxk",
450 "dp":"G4sPXkc6Ya9y8oJW9_ILj4xuppu0lzi_H7VTkS8xj5SdX3coE0oimYwxIi2emTAue0UOa5dpgFGyBJ4c8tQ2VF402XRugKDTP8akYhFo5tAA77Qe_NmtuYZc3C3m3I24G2GvR5sSDxUyAN2zq8Lfn9EUms6rY3Ob8YeiKkTiBj0",
451 "dq":"s9lAH9fggBsoFR8Oac2R_E2gw282rT2kGOAhvIllETE1efrA6huUUvMfBcMpn8lqeW6vzznYY5SSQF7pMdC_agI3nG8Ibp1BUb0JUiraRNqUfLhcQb_d9GF4Dh7e74WbRsobRonujTYN1xCaP6TO61jvWrX-L18txXw494Q_cgk",
452 "qi":"GyM_p6JrXySiz1toFgKbWV-JdI3jQ4ypu9rbMWx3rQJBfmt0FoYzgUIZEVFEcOqwemRN81zoDAaa-Bk0KWNGDjJHZDdDmFhW3AN7lI-puxk_mHZGJ11rxyR8O55XLSe3SPmRfKwZI6yU24ZxvQKFYItdldUKGzO6Ia6zTKhAVRU",
453 "alg":"RS256",
454 "kid":"2011-04-29"
455 }`
456 verify(t, src, reflect.TypeOf((*jwk.RSAPrivateKey)(nil)).Elem())
457 })
458 t.Run("ECDSA Private Key", func(t *testing.T) {
459 t.Parallel()
460 const src = `{
461 "kty" : "EC",
462 "crv" : "P-256",
463 "x" : "SVqB4JcUD6lsfvqMr-OKUNUphdNn64Eay60978ZlL74",
464 "y" : "lf0u0pMj4lGAzZix5u4Cm5CMQIgMNpkwy163wtKYVKI",
465 "d" : "0g5vAEKzugrXaRbgKG0Tj2qJ5lMP4Bezds1_sTybkfk"
466 }`
467 verify(t, src, reflect.TypeOf((*jwk.ECDSAPrivateKey)(nil)).Elem())
468 })
469 t.Run("Invalid ECDSA Private Key", func(t *testing.T) {
470 t.Parallel()
471 const src = `{
472 "kty" : "EC",
473 "crv" : "P-256",
474 "y" : "lf0u0pMj4lGAzZix5u4Cm5CMQIgMNpkwy163wtKYVKI",
475 "d" : "0g5vAEKzugrXaRbgKG0Tj2qJ5lMP4Bezds1_sTybkfk"
476 }`
477 _, err := jwk.ParseString(src)
478 if !assert.Error(t, err, `jwk.ParseString should fail`) {
479 return
480 }
481 })
482 t.Run("Ed25519 Public Key", func(t *testing.T) {
483 t.Parallel()
484
485 const src = `{
486 "kty" : "OKP",
487 "crv" : "Ed25519",
488 "x" : "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo"
489 }`
490 verify(t, src, reflect.TypeOf((*jwk.OKPPublicKey)(nil)).Elem())
491 })
492 t.Run("Ed25519 Private Key", func(t *testing.T) {
493 t.Parallel()
494
495 const src = `{
496 "kty" : "OKP",
497 "crv" : "Ed25519",
498 "d" : "nWGxne_9WmC6hEr0kuwsxERJxWl7MmkZcDusAxyuf2A",
499 "x" : "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo"
500 }`
501 verify(t, src, reflect.TypeOf((*jwk.OKPPrivateKey)(nil)).Elem())
502 })
503 t.Run("X25519 Public Key", func(t *testing.T) {
504 t.Parallel()
505
506 const src = `{
507 "kty" : "OKP",
508 "crv" : "X25519",
509 "x" : "3p7bfXt9wbTTW2HC7OQ1Nz-DQ8hbeGdNrfx-FG-IK08"
510 }`
511 verify(t, src, reflect.TypeOf((*jwk.OKPPublicKey)(nil)).Elem())
512 })
513 t.Run("X25519 Private Key", func(t *testing.T) {
514 t.Parallel()
515
516 const src = `{
517 "kty" : "OKP",
518 "crv" : "X25519",
519 "d" : "dwdtCnMYpX08FsFyUbJmRd9ML4frwJkqsXf7pR25LCo",
520 "x" : "hSDwCYkwp1R0i33ctD73Wg2_Og0mOBr066SpjqqbTmo"
521 }`
522 verify(t, src, reflect.TypeOf((*jwk.OKPPrivateKey)(nil)).Elem())
523 })
524 }
525
526 func TestRoundtrip(t *testing.T) {
527 t.Parallel()
528 generateRSA := func(use string, keyID string) (jwk.Key, error) {
529 k, err := jwxtest.GenerateRsaJwk()
530 if err != nil {
531 return nil, err
532 }
533
534 k.Set(jwk.KeyUsageKey, use)
535 k.Set(jwk.KeyIDKey, keyID)
536 return k, nil
537 }
538
539 generateECDSA := func(use, keyID string) (jwk.Key, error) {
540 k, err := jwxtest.GenerateEcdsaJwk()
541 if err != nil {
542 return nil, err
543 }
544
545 k.Set(jwk.KeyUsageKey, use)
546 k.Set(jwk.KeyIDKey, keyID)
547 return k, nil
548 }
549
550 generateSymmetric := func(use, keyID string) (jwk.Key, error) {
551 k, err := jwxtest.GenerateSymmetricJwk()
552 if err != nil {
553 return nil, err
554 }
555
556 k.Set(jwk.KeyUsageKey, use)
557 k.Set(jwk.KeyIDKey, keyID)
558 return k, nil
559 }
560
561 generateEd25519 := func(use, keyID string) (jwk.Key, error) {
562 k, err := jwxtest.GenerateEd25519Jwk()
563 if err != nil {
564 return nil, err
565 }
566
567 k.Set(jwk.KeyUsageKey, use)
568 k.Set(jwk.KeyIDKey, keyID)
569 return k, nil
570 }
571
572 generateX25519 := func(use, keyID string) (jwk.Key, error) {
573 k, err := jwxtest.GenerateX25519Jwk()
574 if err != nil {
575 return nil, err
576 }
577
578 k.Set(jwk.KeyUsageKey, use)
579 k.Set(jwk.KeyIDKey, keyID)
580 return k, nil
581 }
582
583 tests := []struct {
584 generate func(string, string) (jwk.Key, error)
585 use string
586 keyID string
587 }{
588 {
589 use: "enc",
590 keyID: "enc1",
591 generate: generateRSA,
592 },
593 {
594 use: "enc",
595 keyID: "enc2",
596 generate: generateRSA,
597 },
598 {
599 use: "sig",
600 keyID: "sig1",
601 generate: generateRSA,
602 },
603 {
604 use: "sig",
605 keyID: "sig2",
606 generate: generateRSA,
607 },
608 {
609 use: "sig",
610 keyID: "sig3",
611 generate: generateSymmetric,
612 },
613 {
614 use: "enc",
615 keyID: "enc4",
616 generate: generateECDSA,
617 },
618 {
619 use: "enc",
620 keyID: "enc5",
621 generate: generateECDSA,
622 },
623 {
624 use: "sig",
625 keyID: "sig4",
626 generate: generateECDSA,
627 },
628 {
629 use: "sig",
630 keyID: "sig5",
631 generate: generateECDSA,
632 },
633 {
634 use: "sig",
635 keyID: "sig6",
636 generate: generateEd25519,
637 },
638 {
639 use: "enc",
640 keyID: "enc6",
641 generate: generateX25519,
642 },
643 }
644
645 ks1 := jwk.NewSet()
646 for _, tc := range tests {
647 key, err := tc.generate(tc.use, tc.keyID)
648 if !assert.NoError(t, err, `tc.generate should succeed`) {
649 return
650 }
651 if !assert.True(t, ks1.Add(key), `ks1.Add should succeed`) {
652 return
653 }
654 }
655
656 buf, err := json.MarshalIndent(ks1, "", " ")
657 if !assert.NoError(t, err, "JSON marshal succeeded") {
658 return
659 }
660
661 ks2, err := jwk.Parse(buf)
662 if !assert.NoError(t, err, "JSON unmarshal succeeded") {
663 t.Logf("%s", buf)
664 return
665 }
666
667 for _, tc := range tests {
668 key1, ok := ks2.LookupKeyID(tc.keyID)
669 if !assert.True(t, ok, "ks2.LookupKeyID should succeed") {
670 return
671 }
672
673 key2, ok := ks1.LookupKeyID(tc.keyID)
674 if !assert.True(t, ok, "ks1.LookupKeyID should succeed") {
675 return
676 }
677
678 pk1json, _ := json.Marshal(key1)
679 pk2json, _ := json.Marshal(key2)
680 if !assert.Equal(t, pk1json, pk2json, "Keys should match (kid = %s)", tc.keyID) {
681 return
682 }
683 }
684 }
685
686 func TestAccept(t *testing.T) {
687 t.Parallel()
688 t.Run("KeyOperation", func(t *testing.T) {
689 t.Parallel()
690 testcases := []struct {
691 Args interface{}
692 Error bool
693 }{
694 {
695 Args: "sign",
696 },
697 {
698 Args: []jwk.KeyOperation{jwk.KeyOpSign, jwk.KeyOpVerify, jwk.KeyOpEncrypt, jwk.KeyOpDecrypt, jwk.KeyOpWrapKey, jwk.KeyOpUnwrapKey},
699 },
700 {
701 Args: jwk.KeyOperationList{jwk.KeyOpSign, jwk.KeyOpVerify, jwk.KeyOpEncrypt, jwk.KeyOpDecrypt, jwk.KeyOpWrapKey, jwk.KeyOpUnwrapKey},
702 },
703 {
704 Args: []interface{}{"sign", "verify", "encrypt", "decrypt", "wrapKey", "unwrapKey"},
705 },
706 {
707 Args: []string{"sign", "verify", "encrypt", "decrypt", "wrapKey", "unwrapKey"},
708 },
709 {
710 Args: []string{"sigh"},
711 Error: true,
712 },
713 }
714
715 for _, test := range testcases {
716 var ops jwk.KeyOperationList
717 if test.Error {
718 if !assert.Error(t, ops.Accept(test.Args), `KeyOperationList.Accept should fail`) {
719 return
720 }
721 } else {
722 if !assert.NoError(t, ops.Accept(test.Args), `KeyOperationList.Accept should succeed`) {
723 return
724 }
725 }
726 }
727 })
728 t.Run("KeyUsage", func(t *testing.T) {
729 t.Parallel()
730 testcases := []struct {
731 Args interface{}
732 Error bool
733 }{
734 {Args: jwk.ForSignature},
735 {Args: jwk.ForEncryption},
736 {Args: jwk.ForSignature.String()},
737 {Args: jwk.ForEncryption.String()},
738 {Args: jwk.KeyUsageType("bogus"), Error: true},
739 {Args: "bogus", Error: true},
740 }
741 for _, test := range testcases {
742 var usage jwk.KeyUsageType
743 if test.Error {
744 if !assert.Error(t, usage.Accept(test.Args), `KeyUsage.Accept should fail`) {
745 return
746 }
747 } else {
748 if !assert.NoError(t, usage.Accept(test.Args), `KeyUsage.Accept should succeed`) {
749 return
750 }
751 }
752 }
753 })
754 }
755
756 func TestAssignKeyID(t *testing.T) {
757 t.Parallel()
758 generators := []func() (jwk.Key, error){
759 jwxtest.GenerateRsaJwk,
760 jwxtest.GenerateRsaPublicJwk,
761 jwxtest.GenerateEcdsaJwk,
762 jwxtest.GenerateEcdsaPublicJwk,
763 jwxtest.GenerateSymmetricJwk,
764 jwxtest.GenerateEd25519Jwk,
765 }
766
767 for _, generator := range generators {
768 k, err := generator()
769 if !assert.NoError(t, err, `jwk generation should be successful`) {
770 return
771 }
772
773 if !assert.Empty(t, k.KeyID(), `k.KeyID should be non-empty`) {
774 return
775 }
776 if !assert.NoError(t, jwk.AssignKeyID(k), `AssignKeyID shuld be successful`) {
777 return
778 }
779
780 if !assert.NotEmpty(t, k.KeyID(), `k.KeyID should be non-empty`) {
781 return
782 }
783 }
784 }
785
786 func TestPublicKeyOf(t *testing.T) {
787 t.Parallel()
788
789 rsakey, err := jwxtest.GenerateRsaKey()
790 if !assert.NoError(t, err, `generating raw RSA key should succeed`) {
791 return
792 }
793
794 ecdsakey, err := jwxtest.GenerateEcdsaKey(jwa.P521)
795 if !assert.NoError(t, err, `generating raw ECDSA key should succeed`) {
796 return
797 }
798
799 octets := jwxtest.GenerateSymmetricKey()
800
801 ed25519key, err := jwxtest.GenerateEd25519Key()
802 if !assert.NoError(t, err, `generating raw Ed25519 key should succeed`) {
803 return
804 }
805
806 x25519key, err := jwxtest.GenerateX25519Key()
807 if !assert.NoError(t, err, `generating raw X25519 key should succeed`) {
808 return
809 }
810
811 keys := []struct {
812 Key interface{}
813 PublicKeyType reflect.Type
814 }{
815 {
816 Key: rsakey,
817 PublicKeyType: reflect.PtrTo(reflect.TypeOf(rsakey.PublicKey)),
818 },
819 {
820 Key: *rsakey,
821 PublicKeyType: reflect.PtrTo(reflect.TypeOf(rsakey.PublicKey)),
822 },
823 {
824 Key: rsakey.PublicKey,
825 PublicKeyType: reflect.PtrTo(reflect.TypeOf(rsakey.PublicKey)),
826 },
827 {
828 Key: &rsakey.PublicKey,
829 PublicKeyType: reflect.PtrTo(reflect.TypeOf(rsakey.PublicKey)),
830 },
831 {
832 Key: ecdsakey,
833 PublicKeyType: reflect.PtrTo(reflect.TypeOf(ecdsakey.PublicKey)),
834 },
835 {
836 Key: *ecdsakey,
837 PublicKeyType: reflect.PtrTo(reflect.TypeOf(ecdsakey.PublicKey)),
838 },
839 {
840 Key: ecdsakey.PublicKey,
841 PublicKeyType: reflect.PtrTo(reflect.TypeOf(ecdsakey.PublicKey)),
842 },
843 {
844 Key: &ecdsakey.PublicKey,
845 PublicKeyType: reflect.PtrTo(reflect.TypeOf(ecdsakey.PublicKey)),
846 },
847 {
848 Key: octets,
849 PublicKeyType: reflect.TypeOf(octets),
850 },
851 {
852 Key: ed25519key,
853 PublicKeyType: reflect.TypeOf(ed25519key.Public()),
854 },
855 {
856 Key: ed25519key.Public(),
857 PublicKeyType: reflect.TypeOf(ed25519key.Public()),
858 },
859 {
860 Key: x25519key,
861 PublicKeyType: reflect.TypeOf(x25519key.Public()),
862 },
863 {
864 Key: x25519key.Public(),
865 PublicKeyType: reflect.TypeOf(x25519key.Public()),
866 },
867 }
868
869 for _, key := range keys {
870 key := key
871 t.Run(fmt.Sprintf("%T", key.Key), func(t *testing.T) {
872 t.Parallel()
873
874 pubkey, err := jwk.PublicRawKeyOf(key.Key)
875 if !assert.NoError(t, err, `jwk.PublicKeyOf(%T) should succeed`, key.Key) {
876 return
877 }
878
879 if !assert.Equal(t, key.PublicKeyType, reflect.TypeOf(pubkey), `public key types should match (got %T)`, pubkey) {
880 return
881 }
882
883
884 jwkKey, err := jwk.New(key.Key)
885 if !assert.NoError(t, err, `jwk.New should succeed`) {
886 return
887 }
888
889 pubJwkKey, err := jwk.PublicKeyOf(jwkKey)
890 if !assert.NoError(t, err, `jwk.PublicKeyOf(%T) should succeed`, jwkKey) {
891 return
892 }
893
894
895 var rawKey interface{}
896 if !assert.NoError(t, pubJwkKey.Raw(&rawKey), `pubJwkKey.Raw should succeed`) {
897 return
898 }
899
900 if !assert.Equal(t, key.PublicKeyType, reflect.TypeOf(rawKey), `public key types should match (got %T)`, rawKey) {
901 return
902 }
903 })
904 }
905 t.Run("Set", func(t *testing.T) {
906 var setKeys []struct {
907 Key jwk.Key
908 PublicKeyType reflect.Type
909 }
910 set := jwk.NewSet()
911 count := 0
912 for _, key := range keys {
913 if reflect.TypeOf(key.Key) == key.PublicKeyType {
914 continue
915 }
916 jwkKey, err := jwk.New(key.Key)
917 if !assert.NoError(t, err, `jwk.New should succeed`) {
918 return
919 }
920 jwkKey.Set(jwk.KeyIDKey, fmt.Sprintf("key%d", count))
921 setKeys = append(setKeys, struct {
922 Key jwk.Key
923 PublicKeyType reflect.Type
924 }{
925 Key: jwkKey,
926 PublicKeyType: key.PublicKeyType,
927 })
928 set.Add(jwkKey)
929 count++
930 }
931
932 newSet, err := jwk.PublicSetOf(set)
933 if !assert.NoError(t, err, `jwk.PublicKeyOf(jwk.Set) should succeed`) {
934 return
935 }
936
937 for i, key := range setKeys {
938 setKey, ok := newSet.Get(i)
939 if !assert.True(t, ok, `element %d should be present`, i) {
940 return
941 }
942
943 if !assert.Equal(t, fmt.Sprintf("key%d", i), setKey.KeyID(), `KeyID() should match for %T`, setKey) {
944 return
945 }
946
947
948 var rawKey interface{}
949 if !assert.NoError(t, setKey.Raw(&rawKey), `pubJwkKey.Raw should succeed`) {
950 return
951 }
952
953 if !assert.Equal(t, key.PublicKeyType, reflect.TypeOf(rawKey), `public key types should match (got %T)`, rawKey) {
954 return
955 }
956 }
957 })
958 }
959
960 func TestIssue207(t *testing.T) {
961 t.Parallel()
962 const src = `{"kty":"EC","alg":"ECMR","crv":"P-521","key_ops":["deriveKey"],"x":"AJwCS845x9VljR-fcrN2WMzIJHDYuLmFShhyu8ci14rmi2DMFp8txIvaxG8n7ZcODeKIs1EO4E_Bldm_pxxs8cUn","y":"ASjz754cIQHPJObihPV8D7vVNfjp_nuwP76PtbLwUkqTk9J1mzCDKM3VADEk-Z1tP-DHiwib6If8jxnb_FjNkiLJ"}`
963
964
965
966 for i := 0; i < 10; i++ {
967 k, err := jwk.ParseKey([]byte(src))
968 if !assert.NoError(t, err, `jwk.ParseKey should succeed`) {
969 return
970 }
971
972 thumb, err := k.Thumbprint(crypto.SHA1)
973 if !assert.NoError(t, err, `k.Thumbprint should succeed`) {
974 return
975 }
976
977 if !assert.Equal(t, `2Mc_43O_BOrOJTNrGX7uJ6JsIYE`, base64.EncodeToString(thumb), `thumbprints should match`) {
978 return
979 }
980 }
981 }
982
983 func TestIssue270(t *testing.T) {
984 t.Parallel()
985 const src = `{"kty":"EC","alg":"ECMR","crv":"P-521","key_ops":["deriveKey"],"x":"AJwCS845x9VljR-fcrN2WMzIJHDYuLmFShhyu8ci14rmi2DMFp8txIvaxG8n7ZcODeKIs1EO4E_Bldm_pxxs8cUn","y":"ASjz754cIQHPJObihPV8D7vVNfjp_nuwP76PtbLwUkqTk9J1mzCDKM3VADEk-Z1tP-DHiwib6If8jxnb_FjNkiLJ"}`
986 k, err := jwk.ParseKey([]byte(src))
987 if !assert.NoError(t, err, `jwk.ParseKey should succeed`) {
988 return
989 }
990
991 for _, usage := range []string{"sig", "enc"} {
992 if !assert.NoError(t, k.Set(jwk.KeyUsageKey, usage)) {
993 return
994 }
995 if !assert.NoError(t, k.Set(jwk.KeyUsageKey, jwk.KeyUsageType(usage))) {
996 return
997 }
998 }
999 }
1000
1001 func TestReadFile(t *testing.T) {
1002 t.Parallel()
1003 if !jose.Available() {
1004 t.SkipNow()
1005 }
1006
1007 ctx, cancel := context.WithCancel(context.Background())
1008 defer cancel()
1009
1010 fn, clean, err := jose.GenerateJwk(ctx, t, `{"alg": "RS256"}`)
1011 if !assert.NoError(t, err, `jose.GenerateJwk`) {
1012 return
1013 }
1014
1015 defer clean()
1016 if _, err := jwk.ReadFile(fn); !assert.NoError(t, err, `jwk.ReadFile should succeed`) {
1017 return
1018 }
1019 }
1020
1021 func TestRSA(t *testing.T) {
1022 t.Parallel()
1023 t.Run("PublicKey", func(t *testing.T) {
1024 t.Parallel()
1025 VerifyKey(t, map[string]keyDef{
1026 jwk.RSAEKey: expectBase64(keyDef{
1027 Method: "E",
1028 Value: "AQAB",
1029 }),
1030 jwk.KeyTypeKey: {
1031 Method: "KeyType",
1032 Value: jwa.RSA,
1033 },
1034 jwk.RSANKey: expectBase64(keyDef{
1035 Method: "N",
1036 Value: "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
1037 }),
1038 })
1039 t.Run("New", func(t *testing.T) {
1040 for _, raw := range []rsa.PublicKey{
1041 {},
1042 } {
1043 _, err := jwk.New(raw)
1044 if !assert.Error(t, err, `jwk.New should fail for invalid key`) {
1045 return
1046 }
1047 }
1048 })
1049 })
1050 t.Run("Private Key", func(t *testing.T) {
1051 t.Parallel()
1052 VerifyKey(t, map[string]keyDef{
1053 jwk.KeyTypeKey: {
1054 Method: "KeyType",
1055 Value: jwa.RSA,
1056 },
1057 jwk.RSANKey: expectBase64(keyDef{
1058 Method: "N",
1059 Value: "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
1060 }),
1061 jwk.RSAEKey: expectBase64(keyDef{
1062 Method: "E",
1063 Value: "AQAB",
1064 }),
1065 jwk.RSADKey: expectBase64(keyDef{
1066 Method: "D",
1067 Value: "X4cTteJY_gn4FYPsXB8rdXix5vwsg1FLN5E3EaG6RJoVH-HLLKD9M7dx5oo7GURknchnrRweUkC7hT5fJLM0WbFAKNLWY2vv7B6NqXSzUvxT0_YSfqijwp3RTzlBaCxWp4doFk5N2o8Gy_nHNKroADIkJ46pRUohsXywbReAdYaMwFs9tv8d_cPVY3i07a3t8MN6TNwm0dSawm9v47UiCl3Sk5ZiG7xojPLu4sbg1U2jx4IBTNBznbJSzFHK66jT8bgkuqsk0GjskDJk19Z4qwjwbsnn4j2WBii3RL-Us2lGVkY8fkFzme1z0HbIkfz0Y6mqnOYtqc0X4jfcKoAC8Q",
1068 }),
1069 jwk.RSAPKey: expectBase64(keyDef{
1070 Method: "P",
1071 Value: "83i-7IvMGXoMXCskv73TKr8637FiO7Z27zv8oj6pbWUQyLPQBQxtPVnwD20R-60eTDmD2ujnMt5PoqMrm8RfmNhVWDtjjMmCMjOpSXicFHj7XOuVIYQyqVWlWEh6dN36GVZYk93N8Bc9vY41xy8B9RzzOGVQzXvNEvn7O0nVbfs",
1072 }),
1073 jwk.RSAQKey: expectBase64(keyDef{
1074 Method: "Q",
1075 Value: "3dfOR9cuYq-0S-mkFLzgItgMEfFzB2q3hWehMuG0oCuqnb3vobLyumqjVZQO1dIrdwgTnCdpYzBcOfW5r370AFXjiWft_NGEiovonizhKpo9VVS78TzFgxkIdrecRezsZ-1kYd_s1qDbxtkDEgfAITAG9LUnADun4vIcb6yelxk",
1076 }),
1077 jwk.RSADPKey: expectBase64(keyDef{
1078 Method: "DP",
1079 Value: "G4sPXkc6Ya9y8oJW9_ILj4xuppu0lzi_H7VTkS8xj5SdX3coE0oimYwxIi2emTAue0UOa5dpgFGyBJ4c8tQ2VF402XRugKDTP8akYhFo5tAA77Qe_NmtuYZc3C3m3I24G2GvR5sSDxUyAN2zq8Lfn9EUms6rY3Ob8YeiKkTiBj0",
1080 }),
1081 jwk.RSADQKey: expectBase64(keyDef{
1082 Method: "DQ",
1083 Value: "s9lAH9fggBsoFR8Oac2R_E2gw282rT2kGOAhvIllETE1efrA6huUUvMfBcMpn8lqeW6vzznYY5SSQF7pMdC_agI3nG8Ibp1BUb0JUiraRNqUfLhcQb_d9GF4Dh7e74WbRsobRonujTYN1xCaP6TO61jvWrX-L18txXw494Q_cgk",
1084 }),
1085 jwk.RSAQIKey: expectBase64(keyDef{
1086 Method: "QI",
1087 Value: "GyM_p6JrXySiz1toFgKbWV-JdI3jQ4ypu9rbMWx3rQJBfmt0FoYzgUIZEVFEcOqwemRN81zoDAaa-Bk0KWNGDjJHZDdDmFhW3AN7lI-puxk_mHZGJ11rxyR8O55XLSe3SPmRfKwZI6yU24ZxvQKFYItdldUKGzO6Ia6zTKhAVRU",
1088 }),
1089 })
1090 t.Run("New", func(t *testing.T) {
1091 for _, raw := range []rsa.PrivateKey{
1092 {},
1093 {
1094 D: &big.Int{},
1095 },
1096 {
1097 D: &big.Int{},
1098 Primes: []*big.Int{nil, {}},
1099 },
1100 {
1101 D: &big.Int{},
1102 Primes: []*big.Int{{}, nil},
1103 },
1104 {
1105 D: &big.Int{},
1106 Primes: []*big.Int{{}, {}},
1107 },
1108 } {
1109 _, err := jwk.New(raw)
1110 if !assert.Error(t, err, `jwk.New should fail for empty key`) {
1111 return
1112 }
1113 }
1114 })
1115 })
1116 t.Run("Thumbprint", func(t *testing.T) {
1117 expected := []byte{55, 54, 203, 177, 120, 124, 184, 48, 156, 119, 238,
1118 140, 55, 5, 197, 225, 111, 251, 158, 133, 151, 21, 144, 31, 30, 76, 89,
1119 177, 17, 130, 245, 123,
1120 }
1121 const src = `{
1122 "kty":"RSA",
1123 "e": "AQAB",
1124 "n": "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw"
1125 }`
1126
1127 key, err := jwk.ParseKey([]byte(src))
1128 if !assert.NoError(t, err, `jwk.ParseKey should succeed`) {
1129 return
1130 }
1131
1132 tp, err := key.Thumbprint(crypto.SHA256)
1133 if !assert.NoError(t, err, "Thumbprint should succeed") {
1134 return
1135 }
1136
1137 if !assert.Equal(t, expected, tp, "Thumbprint should match") {
1138 return
1139 }
1140 })
1141 }
1142
1143 func TestECDSA(t *testing.T) {
1144 t.Run("PrivateKey", func(t *testing.T) {
1145 t.Run("New", func(t *testing.T) {
1146 for _, raw := range []ecdsa.PrivateKey{
1147 {},
1148 {
1149 D: &big.Int{},
1150 },
1151 {
1152 D: &big.Int{},
1153 PublicKey: ecdsa.PublicKey{
1154 Y: &big.Int{},
1155 },
1156 },
1157 {
1158 D: &big.Int{},
1159 PublicKey: ecdsa.PublicKey{
1160 X: &big.Int{},
1161 },
1162 },
1163 } {
1164 _, err := jwk.New(raw)
1165 if !assert.Error(t, err, `jwk.New should fail for invalid key`) {
1166 return
1167 }
1168 }
1169 })
1170 VerifyKey(t, map[string]keyDef{
1171 jwk.KeyTypeKey: {
1172 Method: "KeyType",
1173 Value: jwa.EC,
1174 },
1175 jwk.ECDSACrvKey: {
1176 Method: "Crv",
1177 Value: jwa.P256,
1178 },
1179 jwk.ECDSAXKey: expectBase64(keyDef{
1180 Method: "X",
1181 Value: "MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4",
1182 }),
1183 jwk.ECDSAYKey: expectBase64(keyDef{
1184 Method: "Y",
1185 Value: "4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM",
1186 }),
1187 jwk.ECDSADKey: expectBase64(keyDef{
1188 Method: "D",
1189 Value: "870MB6gfuTJ4HtUnUvYMyJpr5eUZNP4Bk43bVdj3eAE",
1190 }),
1191 })
1192 })
1193 t.Run("PublicKey", func(t *testing.T) {
1194 t.Run("New", func(t *testing.T) {
1195 for _, raw := range []ecdsa.PublicKey{
1196 {},
1197 {
1198 Y: &big.Int{},
1199 },
1200 {
1201 X: &big.Int{},
1202 },
1203 } {
1204 _, err := jwk.New(raw)
1205 if !assert.Error(t, err, `jwk.New should fail for invalid key`) {
1206 return
1207 }
1208 }
1209 })
1210 VerifyKey(t, map[string]keyDef{
1211 jwk.KeyTypeKey: {
1212 Method: "KeyType",
1213 Value: jwa.EC,
1214 },
1215 jwk.ECDSACrvKey: {
1216 Method: "Crv",
1217 Value: jwa.P256,
1218 },
1219 jwk.ECDSAXKey: expectBase64(keyDef{
1220 Method: "X",
1221 Value: "MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4",
1222 }),
1223 jwk.ECDSAYKey: expectBase64(keyDef{
1224 Method: "Y",
1225 Value: "4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM",
1226 }),
1227 })
1228 })
1229 t.Run("Curve types", func(t *testing.T) {
1230 for _, alg := range ecutil.AvailableAlgorithms() {
1231 alg := alg
1232 t.Run(alg.String(), func(t *testing.T) {
1233 key, err := jwxtest.GenerateEcdsaKey(alg)
1234 if !assert.NoError(t, err, `jwxtest.GenerateEcdsaKey should succeed`) {
1235 return
1236 }
1237
1238 privkey := jwk.NewECDSAPrivateKey()
1239 if !assert.NoError(t, privkey.FromRaw(key), `privkey.FromRaw should succeed`) {
1240 return
1241 }
1242 pubkey := jwk.NewECDSAPublicKey()
1243 if !assert.NoError(t, pubkey.FromRaw(&key.PublicKey), `pubkey.FromRaw should succeed`) {
1244 return
1245 }
1246
1247 privtp, err := privkey.Thumbprint(crypto.SHA512)
1248 if !assert.NoError(t, err, `privkey.Thumbprint should succeed`) {
1249 return
1250 }
1251
1252 pubtp, err := pubkey.Thumbprint(crypto.SHA512)
1253 if !assert.NoError(t, err, `pubkey.Thumbprint should succeed`) {
1254 return
1255 }
1256
1257 if !assert.Equal(t, privtp, pubtp, `Thumbprints should match`) {
1258 return
1259 }
1260 })
1261 }
1262 })
1263 }
1264
1265 func TestSymmetric(t *testing.T) {
1266 t.Run("Key", func(t *testing.T) {
1267 VerifyKey(t, map[string]keyDef{
1268 jwk.KeyTypeKey: {
1269 Method: "KeyType",
1270 Value: jwa.OctetSeq,
1271 },
1272 jwk.SymmetricOctetsKey: expectBase64(keyDef{
1273 Method: "Octets",
1274 Value: "aGVsbG8K",
1275 }),
1276 })
1277 })
1278 }
1279
1280 func TestOKP(t *testing.T) {
1281 t.Parallel()
1282
1283 t.Run("Ed25519", func(t *testing.T) {
1284 t.Parallel()
1285 t.Run("PrivateKey", func(t *testing.T) {
1286 t.Parallel()
1287 VerifyKey(t, map[string]keyDef{
1288 jwk.KeyTypeKey: {
1289 Method: "KeyType",
1290 Value: jwa.OKP,
1291 },
1292 jwk.OKPDKey: expectBase64(keyDef{
1293 Method: "D",
1294 Value: "nWGxne_9WmC6hEr0kuwsxERJxWl7MmkZcDusAxyuf2A",
1295 }),
1296 jwk.OKPXKey: expectBase64(keyDef{
1297 Method: "X",
1298 Value: "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo",
1299 }),
1300 jwk.OKPCrvKey: {
1301 Method: "Crv",
1302 Value: jwa.Ed25519,
1303 },
1304 })
1305 })
1306 t.Run("PublicKey", func(t *testing.T) {
1307 t.Parallel()
1308 VerifyKey(t, map[string]keyDef{
1309 jwk.KeyTypeKey: {
1310 Method: "KeyType",
1311 Value: jwa.OKP,
1312 },
1313 jwk.OKPXKey: expectBase64(keyDef{
1314 Method: "X",
1315 Value: "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo",
1316 }),
1317 jwk.OKPCrvKey: {
1318 Method: "Crv",
1319 Value: jwa.Ed25519,
1320 },
1321 })
1322 })
1323 })
1324 t.Run("X25519", func(t *testing.T) {
1325 t.Parallel()
1326 t.Run("PublicKey", func(t *testing.T) {
1327 t.Parallel()
1328 VerifyKey(t, map[string]keyDef{
1329 jwk.KeyTypeKey: {
1330 Method: "KeyType",
1331 Value: jwa.OKP,
1332 },
1333 jwk.OKPXKey: expectBase64(keyDef{
1334 Method: "X",
1335 Value: "3p7bfXt9wbTTW2HC7OQ1Nz-DQ8hbeGdNrfx-FG-IK08",
1336 }),
1337 jwk.OKPCrvKey: {
1338 Method: "Crv",
1339 Value: jwa.X25519,
1340 },
1341 })
1342 })
1343 })
1344 }
1345
1346 func TestCustomField(t *testing.T) {
1347
1348 jwk.RegisterCustomField(`x-birthday`, time.Time{})
1349 defer jwk.RegisterCustomField(`x-birthday`, nil)
1350
1351 expected := time.Date(2015, 11, 4, 5, 12, 52, 0, time.UTC)
1352 bdaybytes, _ := expected.MarshalText()
1353
1354 var b strings.Builder
1355 b.WriteString(`{"e":"AQAB", "kty":"RSA", "n":"0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw","x-birthday":"`)
1356 b.Write(bdaybytes)
1357 b.WriteString(`"}`)
1358 src := b.String()
1359
1360 t.Run("jwk.ParseKey", func(t *testing.T) {
1361 key, err := jwk.ParseKey([]byte(src))
1362 if !assert.NoError(t, err, `jwk.ParseKey should succeed`) {
1363 return
1364 }
1365
1366 v, ok := key.Get(`x-birthday`)
1367 if !assert.True(t, ok, `key.Get("x-birthday") should succeed`) {
1368 return
1369 }
1370
1371 if !assert.Equal(t, expected, v, `values should match`) {
1372 return
1373 }
1374 })
1375 t.Run("json.Unmarshal", func(t *testing.T) {
1376 key := jwk.NewRSAPublicKey()
1377 if !assert.NoError(t, json.Unmarshal([]byte(src), key), `json.Unmarshal should succeed`) {
1378 return
1379 }
1380
1381 v, ok := key.Get(`x-birthday`)
1382 if !assert.True(t, ok, `key.Get("x-birthday") should succeed`) {
1383 return
1384 }
1385
1386 if !assert.Equal(t, expected, v, `values should match`) {
1387 return
1388 }
1389 })
1390 }
1391
1392 func TestCertificate(t *testing.T) {
1393 const src = `-----BEGIN CERTIFICATE-----
1394 MIIEljCCAn4CCQCTQBoGDvUbQTANBgkqhkiG9w0BAQsFADANMQswCQYDVQQGEwJK
1395 UDAeFw0yMTA0MDEwMDE4MjhaFw0yMjA0MDEwMDE4MjhaMA0xCzAJBgNVBAYTAkpQ
1396 MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvws4H/OxVS3CW1zvUgjs
1397 H443df9zCAblLVPPdeRD11Jl1OZmGS7rtQNjQyT5xGpeuk77ZJcfDNLx+mSEtiYQ
1398 V37GD5MPz+RX3hP2azuLvxoBseaHE6kC8tkDed8buQLl1hgms15KmKnt7E8B+EK2
1399 1YRj0w6ZzehIllTbbj6gDJ39kZ2VHdLf5+4W0Kyh9cM4aA0si2jQJQsohW2rpt89
1400 b+IagFau+sxP3GFUjSEvyXIamXhS0NLWuAW9UvY/RwhnIo5BzmWZd/y2R305T+QT
1401 rHtb/8aGav8mP3uDx6AMDp/0UMKFUO4mpoOusMnrplUPS4Lz6RNpffmrrglOEuRZ
1402 /eSFzGL35OeL12aYSyrbFIVsc/aLs6MkoplsuSG6Zhx345h/dA2a8Ub5khr6bksP
1403 zGLer+bpBrQQsy21unvCIUz5y7uaYhV3Ql+aIZ+dwpEgZ3xxAvdKKeoCGQlhH/4J
1404 0sSuutUtuTLfrBSgLHJEv2HIzeynChL2CYR8aku/nL68VTdmSt9UY2JGMOf9U8BI
1405 fGRpkWBvI8hddMxNm8wF+09WScaZ2JWu7qW/l2jOdgesPIWRg+Hm3NaRSHqAWCOq
1406 VUJk9WkCAye0FPALqSvH0ApDKxNtGZb5JZRCW19TqmhgXbAqIf5hsxDaGIXZcW9S
1407 CqapZPw7Ccs7BOKSFvmM9p0CAwEAATANBgkqhkiG9w0BAQsFAAOCAgEAVfLzKRdA
1408 0vFpAAp3K+CDth7mag2WWFOXjlWZ+4pxfEBX3k7erJbj6+qYuCvCHXqIZnK1kZzD
1409 p4zwsu8t8RfSmPvxcm/jkvecG4DAIGTdhBVtAf/9PU3e4kZFQCqizicQABh+ZFKV
1410 dDtkRebUA5EAvP8E/OrvrjYU5xnOxOZU3arVXJfKFjVD619qLuF8XXW5700Gdqwn
1411 wBgasTCCg9+tniiscKaET1m9C4PdrlXuAIscV9tGcJ7yEAao1BXokyJ+mK6K2Zv1
1412 z/vvUJA/rGMBJoUjnWrRHON1JMNou2KyRO6z37GpRnfPiNgFpGv2x3ZNeix7H4bP
1413 6+x4KZWQir5047p9hV4YrqMXeULEj3uG2GnOgdR7+hiN39arFVr11DMgABmx19SM
1414 VQpTHrC8a605wwCBWnkiYdNojLa5WgeEHdBghKVpWnx9frYgZcz2UP861el5Lg9R
1415 j04wkGL4IORYiM7VHSHNU4u/dlgfQE1y0T+1CzXwquy4csvbBzBKnZ1o9ZBsOtWS
1416 ox0RaBsMD70mvTwKKmlCSD5HgZZTC0CfGWk4dQp/Mct5Z0x0HJMEJCJzpgTn3CRX
1417 z8CjezfckLs7UKJOlhu3OU9TFsiGDzSDBZdDWO1/uciJ/AAWeSmsBt8cKL0MirIr
1418 c4wOvhbalcX0FqTM3mXCgMFRbibquhwdxbU=
1419 -----END CERTIFICATE-----`
1420 key, err := jwk.ParseKey([]byte(src), jwk.WithPEM(true))
1421 if !assert.NoError(t, err, `jwk.ParseKey should succeed`) {
1422 return
1423 }
1424
1425 if !assert.Equal(t, jwa.RSA, key.KeyType(), `key type should be RSA`) {
1426 return
1427 }
1428
1429 var pubkey rsa.PublicKey
1430 if !assert.NoError(t, key.Raw(&pubkey), `key.Raw should succeed`) {
1431 return
1432 }
1433
1434 N := &big.Int{}
1435 N, _ = N.SetString(`779390807991489150242580488277564408218067197694419403671246387831173881192316375931050469298375090533614189460270485948672580508192398132571230359681952349714254730569052029178325305344289615160181016909374016900403698428293142159695593998453788610098596363011884623801134548926432366560975619087466760747503535615491182090094278093592303467050094984372887804234341012289019841973178427045121609424191835554013017436743418746919496835541323790719629313070434897002108079086472354410640690933161025543816362962891190753195691593288890628966181309776957070655619665306995097798188588453327627252794498823229009195585001242181503742627414517186199717150645163224325403559815442522031412813762764879089624715721999552786759649849125487587658121901233329199571710176245013452847516179837767710027433169340850618643815395642568876192931279303797384539146396956216244189819533317558165234451499206045369678277987397913889177569796721689284116762473340601498426367267765652880247655009239893325078809797979771964770948333084772104541394544131668212262901583064272659565503500144472388676955404823979083054620299811247635425415371418720649368570747531327436083928369741631909855731133100553629456091216238379430154237251461586878393695925917`, 10)
1436
1437 if !assert.Equal(t, N, pubkey.N, `value for N should match`) {
1438 return
1439 }
1440
1441 if !assert.Equal(t, 65537, pubkey.E, `value for E should amtch`) {
1442 return
1443 }
1444 }
1445
1446 type typedField struct {
1447 Foo string
1448 Bar int
1449 }
1450
1451 func TestTypedFields(t *testing.T) {
1452 expected := &typedField{Foo: "Foo", Bar: 0xdeadbeef}
1453 var keys []jwk.Key
1454 {
1455 k1, _ := jwxtest.GenerateRsaJwk()
1456 k2, _ := jwxtest.GenerateEcdsaJwk()
1457 k3, _ := jwxtest.GenerateSymmetricJwk()
1458 k4, _ := jwxtest.GenerateEd25519Jwk()
1459 keys = []jwk.Key{k1, k2, k3, k4}
1460 }
1461 for _, key := range keys {
1462 key.Set("typed-field", expected)
1463 }
1464
1465 testcases := []struct {
1466 Name string
1467 Options []jwk.ParseOption
1468 PostProcess func(*testing.T, interface{}) (*typedField, error)
1469 }{
1470 {
1471 Name: "Basic",
1472 Options: []jwk.ParseOption{jwk.WithTypedField("typed-field", typedField{})},
1473 PostProcess: func(t *testing.T, field interface{}) (*typedField, error) {
1474 t.Helper()
1475 v, ok := field.(typedField)
1476 if !ok {
1477 return nil, errors.Errorf(`field value should be of type "typedField", but got %T`, field)
1478 }
1479 return &v, nil
1480 },
1481 },
1482 {
1483 Name: "json.RawMessage",
1484 Options: []jwk.ParseOption{jwk.WithTypedField("typed-field", json.RawMessage{})},
1485 PostProcess: func(t *testing.T, field interface{}) (*typedField, error) {
1486 t.Helper()
1487 v, ok := field.(json.RawMessage)
1488 if !ok {
1489 return nil, errors.Errorf(`field value should be of type "json.RawMessage", but got %T`, field)
1490 }
1491
1492 var c typedField
1493 if err := json.Unmarshal(v, &c); err != nil {
1494 return nil, errors.Wrap(err, `json.Unmarshal failed`)
1495 }
1496
1497 return &c, nil
1498 },
1499 },
1500 }
1501
1502 for _, key := range keys {
1503 key := key
1504 serialized, err := json.Marshal(key)
1505 if !assert.NoError(t, err, `json.Marshal should succeed`) {
1506 return
1507 }
1508
1509 t.Run(fmt.Sprintf("%T", key), func(t *testing.T) {
1510 for _, tc := range testcases {
1511 tc := tc
1512 t.Run(tc.Name, func(t *testing.T) {
1513 got, err := jwk.ParseKey(serialized, tc.Options...)
1514 if !assert.NoError(t, err, `jwk.Parse should succeed`) {
1515 return
1516 }
1517
1518 v, ok := got.Get("typed-field")
1519 if !assert.True(t, ok, `got.Get() should succeed`) {
1520 return
1521 }
1522 field, err := tc.PostProcess(t, v)
1523 if !assert.NoError(t, err, `tc.PostProcess should succeed`) {
1524 return
1525 }
1526
1527 if !assert.Equal(t, field, expected, `field should match expected value`) {
1528 return
1529 }
1530 })
1531 }
1532 })
1533 }
1534
1535 t.Run("Set", func(t *testing.T) {
1536 s := jwk.NewSet()
1537 for _, key := range keys {
1538 s.Add(key)
1539 }
1540
1541 serialized, err := json.Marshal(s)
1542 if !assert.NoError(t, err, `json.Marshal should succeed`) {
1543 return
1544 }
1545
1546 for _, tc := range testcases {
1547 tc := tc
1548 t.Run(tc.Name, func(t *testing.T) {
1549 ctx, cancel := context.WithCancel(context.Background())
1550 defer cancel()
1551
1552 got, err := jwk.Parse(serialized, tc.Options...)
1553 if !assert.NoError(t, err, `jwk.Parse should succeed`) {
1554 return
1555 }
1556
1557 for iter := got.Iterate(ctx); iter.Next(ctx); {
1558 pair := iter.Pair()
1559 key, _ := pair.Value.(jwk.Key)
1560 v, ok := key.Get("typed-field")
1561 if !assert.True(t, ok, `key.Get() should succeed`) {
1562 return
1563 }
1564 field, err := tc.PostProcess(t, v)
1565 if !assert.NoError(t, err, `tc.PostProcess should succeed`) {
1566 return
1567 }
1568
1569 if !assert.Equal(t, field, expected, `field should match expected value`) {
1570 return
1571 }
1572 }
1573 })
1574 }
1575 })
1576 }
1577
1578 func TestGH412(t *testing.T) {
1579 base := jwk.NewSet()
1580
1581 const max = 5
1582 kids := make(map[string]struct{})
1583 for i := 0; i < max; i++ {
1584 k, err := jwxtest.GenerateRsaJwk()
1585 if !assert.NoError(t, err, `jwxttest.GenerateRsaJwk() should succeed`) {
1586 return
1587 }
1588
1589 kid := "key-" + strconv.Itoa(i)
1590 k.Set(jwk.KeyIDKey, kid)
1591 base.Add(k)
1592 kids[kid] = struct{}{}
1593 }
1594
1595 for i := 0; i < max; i++ {
1596 idx := i
1597 currentKid := "key-" + strconv.Itoa(i)
1598 t.Run(fmt.Sprintf("Remove at position %d", i), func(t *testing.T) {
1599 set, err := base.Clone()
1600 if !assert.NoError(t, err, `base.Clone() should succeed`) {
1601 return
1602 }
1603
1604 if !assert.Equal(t, max, set.Len(), `set.Len should be %d`, max) {
1605 return
1606 }
1607
1608 k, ok := set.Get(idx)
1609 if !assert.True(t, ok, `set.Get should succeed`) {
1610 return
1611 }
1612
1613 if !assert.True(t, set.Remove(k), `set.Remove should succeed`) {
1614 return
1615 }
1616 t.Logf("deleted key %s", k.KeyID())
1617
1618 if !assert.Equal(t, max-1, set.Len(), `set.Len should be %d`, max-1) {
1619 return
1620 }
1621
1622 expected := make(map[string]struct{})
1623 for k := range kids {
1624 if k == currentKid {
1625 continue
1626 }
1627 expected[k] = struct{}{}
1628 }
1629
1630 ctx := context.Background()
1631 for iter := set.Iterate(ctx); iter.Next(ctx); {
1632 pair := iter.Pair()
1633 key := pair.Value.(jwk.Key)
1634 if !assert.NotEqual(t, k.KeyID(), key.KeyID(), `key id should not match`) {
1635 return
1636 }
1637 t.Logf("%s found", key.KeyID())
1638 delete(expected, key.KeyID())
1639 }
1640
1641 if !assert.Len(t, expected, 0, `expected map should be empty`) {
1642 return
1643 }
1644 })
1645 }
1646 }
1647
1648 func TestGH491(t *testing.T) {
1649 msg := `{"keys":[{"alg":"ECMR","crv":"P-521","key_ops":["deriveKey"],"kty":"EC","x":"AEFldixpd6xWI1rPigk_i_fW_9SLXh3q3h_CbmRIJ2vmnneWnfylvg37q9_BeSxhLpTQkq580tP-7QiOoNem4ubg","y":"AD8MroFIWQI4nm1rVKOb0ImO0Y7EzPt1HTQfZxagv2IoMez8H_vV7Ra9fU7lJhoe3v-Th6x3-4540FodeIxxiphn"},{"alg":"ES512","crv":"P-521","key_ops":["verify"],"kty":"EC","x":"AFZApUzXzvjVJCZQX1De3LUudI7fiWZcZS3t4F2yrxn0tItCYIZrfygPiCZfV1hVKa3WuH2YMrISZUPrSgi_RN2d","y":"ASEyw-_9xcwNBnvpT7thmAF5qHv9-UPYf38AC7y5QBVejQH_DO1xpKzlTbrHCz0jrMeEir8TyW5ywZIYnqGzPBpn"}]}`
1650 keys, err := jwk.Parse([]byte(msg))
1651 if !assert.NoError(t, err, `jwk.Parse should succeed`) {
1652 return
1653 }
1654
1655
1656 k, _ := keys.Get(0)
1657 ops := k.KeyOps()
1658 if !assert.Equal(t, jwk.KeyOperationList{jwk.KeyOpDeriveKey}, ops, `k.KeyOps should match`) {
1659 return
1660 }
1661 }
1662
1663 func TestSetWithPrivateParams(t *testing.T) {
1664 k1, err := jwxtest.GenerateRsaJwk()
1665 if !assert.NoError(t, err, `jwxtest.GenerateRsaJwk should succeed`) {
1666 return
1667 }
1668 k2, err := jwxtest.GenerateEcdsaJwk()
1669 if !assert.NoError(t, err, `jwxtest.GenerateEcdsaJwk should succeed`) {
1670 return
1671 }
1672 k3, err := jwxtest.GenerateSymmetricJwk()
1673 if !assert.NoError(t, err, `jwxtest.GenerateSymmetricJwk should succeed`) {
1674 return
1675 }
1676
1677 t.Run("JWK instead of JWKS", func(t *testing.T) {
1678 var buf bytes.Buffer
1679 _ = k1.Set(`renewal_kid`, "foo")
1680 _ = json.NewEncoder(&buf).Encode(k1)
1681
1682 var check = func(t *testing.T, buf []byte) {
1683 set, err := jwk.Parse(buf)
1684 if !assert.NoError(t, err, `jwk.Parse should succeed`) {
1685 return
1686 }
1687
1688 if !assert.Equal(t, 1, set.Len(), `set.Len() should be 1`) {
1689 return
1690 }
1691
1692 v, ok := set.Field(`renewal_kid`)
1693 if !assert.True(t, ok, `set.Field("renewal_kid") should return ok = true`) {
1694 return
1695 }
1696
1697 if !assert.Equal(t, `foo`, v, `set.Field("renewal_kid") should return "foo"`) {
1698 return
1699 }
1700
1701 key, ok := set.Get(0)
1702 if !assert.True(t, ok, `set.Get(0) should return ok = true`) {
1703 return
1704 }
1705
1706 v, ok = key.Get(`renewal_kid`)
1707 if !assert.True(t, ok, `key.Get("renewal_kid") should return ok = true`) {
1708 return
1709 }
1710
1711 if !assert.Equal(t, `foo`, v, `key.Get("renewal_kid") should return "foo"`) {
1712 return
1713 }
1714 }
1715
1716 t.Run("Check original buffer", func(t *testing.T) {
1717 check(t, buf.Bytes())
1718 })
1719 t.Run("Check serialized", func(t *testing.T) {
1720 set, err := jwk.Parse(buf.Bytes())
1721 if !assert.NoError(t, err, `jwk.Parse should succeed`) {
1722 return
1723 }
1724 js, err := json.MarshalIndent(set, "", " ")
1725 if !assert.NoError(t, err, `json.MarshalIndent should succeed`) {
1726 return
1727 }
1728 check(t, js)
1729 })
1730 })
1731 t.Run("JWKS with multiple keys", func(t *testing.T) {
1732 var buf bytes.Buffer
1733 buf.WriteString(`{"renewal_kid":"foo","keys":[`)
1734 enc := json.NewEncoder(&buf)
1735 _ = enc.Encode(k1)
1736 buf.WriteByte(',')
1737 _ = enc.Encode(k2)
1738 buf.WriteByte(',')
1739 _ = enc.Encode(k3)
1740 buf.WriteString(`]}`)
1741
1742 var check = func(t *testing.T, buf []byte) {
1743 set, err := jwk.Parse(buf)
1744 if !assert.NoError(t, err, `jwk.Parse should succeed`) {
1745 return
1746 }
1747
1748 if !assert.Equal(t, 3, set.Len(), `set.Len() should be 3`) {
1749 return
1750 }
1751
1752 v, ok := set.Field(`renewal_kid`)
1753 if !assert.True(t, ok, `set.Field("renewal_kid") should return ok = true`) {
1754 return
1755 }
1756
1757 if !assert.Equal(t, `foo`, v, `set.Field("renewal_kid") should return "foo"`) {
1758 return
1759 }
1760 }
1761
1762 t.Run("Check original buffer", func(t *testing.T) {
1763 check(t, buf.Bytes())
1764 })
1765 t.Run("Check serialized", func(t *testing.T) {
1766 set, err := jwk.Parse(buf.Bytes())
1767 if !assert.NoError(t, err, `jwk.Parse should succeed`) {
1768 return
1769 }
1770 js, err := json.MarshalIndent(set, "", " ")
1771 if !assert.NoError(t, err, `json.MarshalIndent should succeed`) {
1772 return
1773 }
1774 check(t, js)
1775 })
1776 })
1777 t.Run("Set private parameters", func(t *testing.T) {
1778 set := jwk.NewSet()
1779 if !assert.NoError(t, set.Set(`renewal_kid`, `foo`), `set.Set should succeed`) {
1780 return
1781 }
1782
1783 v, ok := set.Field(`renewal_kid`)
1784 if !assert.True(t, ok, `set.Get("renewal_kid") should succeed`) {
1785 return
1786 }
1787
1788 if !assert.Equal(t, `foo`, v, `set.Get("renewal_kid") should return "foo"`) {
1789 return
1790 }
1791
1792 if !assert.Error(t, set.Set(`keys`, []string{"foo"}), `set.Set should fail`) {
1793 return
1794 }
1795
1796 k, err := jwk.New([]byte("foobar"))
1797 if !assert.NoError(t, err, `jwk.New should succeed`) {
1798 return
1799 }
1800 keys := []jwk.Key{k}
1801
1802 if !assert.NoError(t, set.Set(`keys`, keys), `set.Set should succeed`) {
1803 return
1804 }
1805
1806 if !assert.Equal(t, set.Len(), 1, `set should have 1 key`) {
1807 return
1808 }
1809 })
1810 }
1811
1812 func TestFetch(t *testing.T) {
1813 k1, err := jwxtest.GenerateRsaJwk()
1814 if !assert.NoError(t, err, `jwxtest.GenerateRsaJwk should succeed`) {
1815 return
1816 }
1817 k2, err := jwxtest.GenerateEcdsaJwk()
1818 if !assert.NoError(t, err, `jwxtest.GenerateEcdsaJwk should succeed`) {
1819 return
1820 }
1821 k3, err := jwxtest.GenerateSymmetricJwk()
1822 if !assert.NoError(t, err, `jwxtest.GenerateSymmetricJwk should succeed`) {
1823 return
1824 }
1825 set := jwk.NewSet()
1826 set.Add(k1)
1827 set.Add(k2)
1828 set.Add(k3)
1829
1830 expected, err := json.MarshalIndent(set, "", " ")
1831 if !assert.NoError(t, err, `json.MarshalIndent should succeed`) {
1832 return
1833 }
1834
1835 srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
1836 w.WriteHeader(http.StatusOK)
1837 w.Write(expected)
1838 }))
1839 defer srv.Close()
1840
1841 testcases := []struct {
1842 Name string
1843 Whitelist func() jwk.Whitelist
1844 Error bool
1845 }{
1846 {
1847 Name: `InsecureWhitelist`,
1848 Whitelist: func() jwk.Whitelist {
1849 return jwk.InsecureWhitelist{}
1850 },
1851 },
1852 {
1853 Name: `MapWhitelist`,
1854 Error: true,
1855 Whitelist: func() jwk.Whitelist {
1856 return jwk.NewMapWhitelist().
1857 Add(`https://www.googleapis.com/oauth2/v3/certs`).
1858 Add(srv.URL)
1859 },
1860 },
1861 {
1862 Name: `RegexpWhitelist`,
1863 Error: true,
1864 Whitelist: func() jwk.Whitelist {
1865 return jwk.NewRegexpWhitelist().
1866 Add(regexp.MustCompile(regexp.QuoteMeta(srv.URL)))
1867 },
1868 },
1869 {
1870 Name: `WhitelistFunc`,
1871 Error: true,
1872 Whitelist: func() jwk.Whitelist {
1873 return jwk.WhitelistFunc(func(s string) bool {
1874 return s == srv.URL
1875 })
1876 },
1877 },
1878 }
1879
1880 for _, tc := range testcases {
1881 tc := tc
1882 t.Run(tc.Name, func(t *testing.T) {
1883 ctx, cancel := context.WithCancel(context.Background())
1884 defer cancel()
1885
1886 wl := tc.Whitelist()
1887
1888 _, err = jwk.Fetch(ctx, `https://github.com/lestrrat-go/jwx`, jwk.WithFetchWhitelist(wl))
1889 if tc.Error {
1890 if !assert.Error(t, err, `jwk.Fetch should fail`) {
1891 return
1892 }
1893 if !assert.True(t, strings.Contains(err.Error(), `rejected by whitelist`), `error should be whitelist error`) {
1894 return
1895 }
1896 }
1897
1898 fetched, err := jwk.Fetch(ctx, srv.URL, jwk.WithFetchWhitelist(wl))
1899 if !assert.NoError(t, err, `jwk.Fetch should succeed`) {
1900 return
1901 }
1902
1903 got, err := json.MarshalIndent(fetched, "", " ")
1904 if !assert.NoError(t, err, `json.MarshalIndent should succeed`) {
1905 return
1906 }
1907
1908 if !assert.Equal(t, expected, got, `data should match`) {
1909 return
1910 }
1911 })
1912 }
1913 }
1914
1915 func TestGH567(t *testing.T) {
1916 const src = `{
1917 "keys": [
1918 {
1919 "kty": "RSA",
1920 "use": "sig",
1921 "kid": "20595A4BE9F566771792BC3DBC7DF78FF9C36575",
1922 "x5t": "20595A4BE9F566771792BC3DBC7DF78FF9C36575",
1923 "e": "AQAB",
1924 "n": "tAN2xCfMuGpZukiGJl_-aQi_HGd4voyEwuOyL79wZphgtAmMAeOEO9QgxSX00ZczonlOm_I1Xpv2RVnNzSiHfB0bTqn4bLt15JVCBhE1vXaRf63QXn5oZ38fxm_aNctfnmkf65sF3lSzcZmfp1934L1KxJObq4BEOpIxvj00gIOpZQ4Mqw1khfsLhIVeXh8xtiEJwQZPdwIUQD03Yt5XQ_QU3NhxmyXiG8c6auOstdZybbGw10uJQEN4PrW0ESvp_GMnLssYrq6x9PhyvJhZhMFX3rBsYhOI7ILMaqo-QeDYUo0lQ1ENoQFyvtWrNQ_6A-CbmJvL9HdN6AuMkujtUmZzEfbT-k3FRyaZL0JE4-yQikdPGHVK6Q2Ho_Zggx2OTNmLbEORBHNe8cbb7t_5fmK6Fk4TpW3795PR8dG-v-AUGpQEgipg5j-3ONxefyBVZyWyjXaxrhQk6nCeRKcXJ0dKiZQX6ykYrtkgwE3mlcuw9-WzUqvHVEMZgAqBhBhL",
1925 "x5c": [
1926 "MIIGpDCCBYygAwIBAgIEX5xBDDANBgkqhkiG9w0BAQsFADBJMQswCQYDVQQGEwJESzESMBAGA1UECgwJVFJVU1QyNDA4MSYwJAYDVQQDDB1UUlVTVDI0MDggU3lzdGVtdGVzdCBYWFhJViBDQTAeFw0yMTA0MjYxMjI1NDBaFw0yNDA0MjYxMTM5NDBaMIGNMQswCQYDVQQGEwJESzEsMCoGA1UECgwjU0lHTkFUVVJHUlVQUEVOIEEvUyAvLyBDVlI6Mjk5MTU5MzgxUDAgBgNVBAUTGUNWUjoyOTkxNTkzOC1VSUQ6NTk5MTEyMjcwLAYDVQQDDCVTSUdOQVRVUkdSVVBQRU4gQS9TIC0gTkVCIFRyYW5zYWN0IFBQMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAtAN2xCfMuGpZukiGJl/\u002BaQi/HGd4voyEwuOyL79wZphgtAmMAeOEO9QgxSX00ZczonlOm/I1Xpv2RVnNzSiHfB0bTqn4bLt15JVCBhE1vXaRf63QXn5oZ38fxm/aNctfnmkf65sF3lSzcZmfp1934L1KxJObq4BEOpIxvj00gIOpZQ4Mqw1khfsLhIVeXh8xtiEJwQZPdwIUQD03Yt5XQ/QU3NhxmyXiG8c6auOstdZybbGw10uJQEN4PrW0ESvp/GMnLssYrq6x9PhyvJhZhMFX3rBsYhOI7ILMaqo\u002BQeDYUo0lQ1ENoQFyvtWrNQ/6A\u002BCbmJvL9HdN6AuMkujtUmZzEfbT\u002Bk3FRyaZL0JE4\u002ByQikdPGHVK6Q2Ho/Zggx2OTNmLbEORBHNe8cbb7t/5fmK6Fk4TpW3795PR8dG\u002Bv\u002BAUGpQEgipg5j\u002B3ONxefyBVZyWyjXaxrhQk6nCeRKcXJ0dKiZQX6ykYrtkgwE3mlcuw9\u002BWzUqvHVEMZgAqBhBhLAgMBAAGjggLNMIICyTAOBgNVHQ8BAf8EBAMCA7gwgZcGCCsGAQUFBwEBBIGKMIGHMDwGCCsGAQUFBzABhjBodHRwOi8vb2NzcC5zeXN0ZW10ZXN0MzQudHJ1c3QyNDA4LmNvbS9yZXNwb25kZXIwRwYIKwYBBQUHMAKGO2h0dHA6Ly92LmFpYS5zeXN0ZW10ZXN0MzQudHJ1c3QyNDA4LmNvbS9zeXN0ZW10ZXN0MzQtY2EuY2VyMIIBIAYDVR0gBIIBFzCCARMwggEPBg0rBgEEAYH0UQIEBgMFMIH9MC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LnRydXN0MjQwOC5jb20vcmVwb3NpdG9yeTCByQYIKwYBBQUHAgIwgbwwDBYFRGFuSUQwAwIBARqBq0RhbklEIHRlc3QgY2VydGlmaWthdGVyIGZyYSBkZW5uZSBDQSB1ZHN0ZWRlcyB1bmRlciBPSUQgMS4zLjYuMS40LjEuMzEzMTMuMi40LjYuMy41LiBEYW5JRCB0ZXN0IGNlcnRpZmljYXRlcyBmcm9tIHRoaXMgQ0EgYXJlIGlzc3VlZCB1bmRlciBPSUQgMS4zLjYuMS40LjEuMzEzMTMuMi40LjYuMy41LjCBrQYDVR0fBIGlMIGiMDygOqA4hjZodHRwOi8vY3JsLnN5c3RlbXRlc3QzNC50cnVzdDI0MDguY29tL3N5c3RlbXRlc3QzNC5jcmwwYqBgoF6kXDBaMQswCQYDVQQGEwJESzESMBAGA1UECgwJVFJVU1QyNDA4MSYwJAYDVQQDDB1UUlVTVDI0MDggU3lzdGVtdGVzdCBYWFhJViBDQTEPMA0GA1UEAwwGQ1JMMTUwMB8GA1UdIwQYMBaAFM1saJc5chmkNatk6vQRo4GH\u002BGk7MB0GA1UdDgQWBBSJJABtTjZRzzFHsb1JwED0qCo49TAJBgNVHRMEAjAAMA0GCSqGSIb3DQEBCwUAA4IBAQA2yBdGVPbKoYUYRZj4bHLj5Xwqk/yh6sodxwAPYrwxkJBzUKFAwUCTCigpwq8NE00kp3xhFT7Hz/9Z7aZLV4N/D94tc0qDU0JIwlbkrn/i3wx8N8UXf242WVaunJLdKqGtV4ijqjZFGa68XBc3elGjnAMY8eoF56dGg35Ps8Cw2BZyG2aXyEQNs6JYUNzp57\u002B6lJWl0T9Zniaut7Aw2rCII8XRe9WY\u002BHIQX6GuBSw0Q4v9wAfyYftnoULsgfVklkxtQI4kAO5rG17Z5NJuvRkXJD8jp\u002B2jRzcaD8Ud\u002Bpe4keTvuJZ\u002BRj\u002BBDLn/3\u002ByPbs3arD3CIO\u002BlW3Nndr34Le/s"
1927 ],
1928 "alg": "RS256"
1929 },
1930 {
1931 "kty": "RSA",
1932 "use": "sig",
1933 "kid": "048058BB59F4D3007045896FD488CE81F4EB4923",
1934 "x5t": "048058BB59F4D3007045896FD488CE81F4EB4923",
1935 "e": "AQAB",
1936 "n": "4bOwMSWoWqOSJoLvwFOCVrKmIO_XX5BCI8KYDIgWjII3a83vwia0a11UHm3B6oPlR3L5udworbH7axrmnPz4GEamQp57Yf0uhnGctlVpVVZHOvXPaMlZgTTGhWpJAGnLnyihZbARgyJefuxZ6ZIqeNyjgc_fC-0J7RWFMxNKS_n6ZKFqQlIlmJInJPWR-YZTuooIb4T4C0JAwFDEvXiAs_fX34Tj1FvD1nv01VPGF5Wx6cBV6fejbRCjY4uFfovhE-dtKX0IakZI8jks-uqMjIOB2x1pOuaqrmrINrTYzKTCKrnMpfaW4urhFmQRKNIgaoLnPgzIb3W9F-vpgrdTjw",
1937 "x5c": [
1938 "MIID/DCCAeSgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBBMQswCQYDVQQGEwJESzEyMDAGA1UEAxMpTmV0cyBlSUQgQnJva2VyIFRva2VuIFNpZ25pbmcgUm9vdCBQUCBFbnYwHhcNMjEwMjI0MDAwMDAwWhcNNDEwMjI0MDAwMDAwWjA\u002BMQswCQYDVQQGEwJESzEvMC0GA1UEAxMmTmV0cyBlSUQgQnJva2VyIFRva2VuIFNpZ25pbmcgMSBQUCBFbnYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDhs7AxJahao5Imgu/AU4JWsqYg79dfkEIjwpgMiBaMgjdrze/CJrRrXVQebcHqg\u002BVHcvm53CitsftrGuac/PgYRqZCnnth/S6GcZy2VWlVVkc69c9oyVmBNMaFakkAacufKKFlsBGDIl5\u002B7Fnpkip43KOBz98L7QntFYUzE0pL\u002BfpkoWpCUiWYkick9ZH5hlO6ighvhPgLQkDAUMS9eICz99ffhOPUW8PWe/TVU8YXlbHpwFXp96NtEKNji4V\u002Bi\u002BET520pfQhqRkjyOSz66oyMg4HbHWk65qquasg2tNjMpMIqucyl9pbi6uEWZBEo0iBqguc\u002BDMhvdb0X6\u002BmCt1OPAgMBAAGjAjAAMA0GCSqGSIb3DQEBCwUAA4ICAQAFKs2PbOIHLgLTNPIhqKCv7Uj\u002Buj0tpF6vO7CFtw1Q0NKo0UB4wD0T9AYu\u002B8sq3M\u002BZjR77eHP6IkvVBEaqBrZgjq6wU1pijPuIUliXF772\u002B/Hr8Wa23iILWevk\u002BleOXDI8kN7E1JPfr0ADsnCJxaXApDqE6Mysd68\u002BGN2adRuvGAcEcKauVfYLAGPQVctkmQSH6VhIJoDKni7gFF/oMZUZ362sOguhlYltcNUMIILJZkFkksRRriHOlz4I8HJiTzWI1Ufuw6iqFWMquOR4BsQZzBSsdPVGlQvjyqOiBia7rPTJE1Z3Kj0mujIbgKTri8YsnFsBynyHq8puYWvMwoGLWu0goxq9rFrINTe39/YpRE6lZUUZU50DddS\u002B0syBTs1H1gX00ofqt6FgWmACc20zJZm2GyhWDtqtiMurn5WKLoZBQrwN5/a6c6HNCStSVxn8o0g9xCgmWM855S8TqHFYXKJSMG00xZZEbsOAPqujkbKakhC/kJQU7XKGjFRskQZhHvpGipFTK4ZapHYYoo5KqZTytAvFENIcuibIk0u8zlCZuXU/PsowMN4G54FftVVyNHuj4TqiKIvB\u002BZNj/zcPopQHHUISVRApR6YO6fqwPxVaJmSTzZ/0uPTaAdnMz5j1wIYf\u002BZDk1ywTxOBRS7/FwNnWAyIuYGFzewY4H2QUNg=="
1939 ],
1940 "alg": "RS256"
1941 },
1942 {
1943 "kty": "RSA",
1944 "use": "enc",
1945 "kid": "A2E10A6BAF4E43E86273F57F218A44B824203176",
1946 "x5t": "A2E10A6BAF4E43E86273F57F218A44B824203176",
1947 "x5c": [
1948 "MIIDGjCCAgKgAwIBAgIIQFkx7rDLvyowDQYJKoZIhvcNAQELBQAwNDEyMDAGA1UEAxMpTmV0cyBlSUQgQnJva2VyIGNsaWVudCByZXF1ZXN0IGVuY3J5cHRpb24wIBcNMjIwMjA5MTQxMDQ1WhgPMjExMjAyMTAxNDEwNDVaMDQxMjAwBgNVBAMTKU5ldHMgZUlEIEJyb2tlciBjbGllbnQgcmVxdWVzdCBlbmNyeXB0aW9uMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAps2R1sxEGxyYfP\u002BK2jq4uDONxrEP4W4oAKJkTv71oOJiK3CBK4ybyk597WufUZfpy8isUKtuqx1x6DTK6vnecUv5KV77/ql6Ac8LJaj5zQBRGuPoPezbD2tPglxp4XEU\u002BqivoyMJiZoLl75MklxvmVVlJQgu1H4RmvdCcp0xYmV2CBX4GKvK6g26y3IZ1FW4Vj5G8eB\u002Bxw423EtsBO3iKPx24BbVZWXC56lhke\u002BQbpbagU/hpQnOdW5tdWdm7oHGUfGwsvg1f6b2Yllwv57ANJkk\u002BfBr\u002BoN0eD2DRNyHbExzJfOBPkDt2FEq1u30kfLP\u002B6ecSByaxSFTl\u002BgFeUUw0wIDAQABoy4wLDALBgNVHQ8EBAMCBBAwHQYDVR0OBBYEFPK08YkmSYK1xNIFEr1AdscfYKnZMA0GCSqGSIb3DQEBCwUAA4IBAQAYeP7IAv3ND\u002B6UMGr9X\u002BP1wURz7UQd66oRldhcdkdS\u002BBNMcU/gVeiU31Es5Y/GhdmKPiuQGdIQdPO88u9A7STWIYUj/lnrgtKif\u002BJ8V/PtfsvHbBYD5f7wFd7fqOpcDFQ2dobOathhrqJ1r3ShFaObpVBX3PL3\u002BSFK3ofHaMYWuIoD\u002BroiOJfIYlL02rrKiiw9r2L9nUCZfSAq3G9rMw\u002BzL38D9BQvrEe9yvwqM3im0m3seiNODiArcY/ee\u002B538\u002BYaToaMPHxUAizREeJFm4aOtwzGND48XHQzbNyfhoSsJesCJsugcNfHUe6o0nuPZ\u002BzvdLrboutrrtxEN8yOm489"
1949 ],
1950 "alg": "http://www.w3.org/2001/04/xmlenc#rsa-oaep"
1951 }
1952 ]
1953 }`
1954
1955 srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
1956 w.Header().Set(`Content-Type`, `application/json`)
1957 w.WriteHeader(http.StatusOK)
1958
1959 io.WriteString(w, src)
1960 }))
1961 defer srv.Close()
1962
1963 for _, ignoreParseError := range []bool{true, false} {
1964 ignoreParseError := ignoreParseError
1965 t.Run(fmt.Sprintf(`Parse with ignoreParseError=%t`, ignoreParseError), func(t *testing.T) {
1966 ctx, cancel := context.WithCancel(context.Background())
1967 defer cancel()
1968
1969 ar := jwk.NewAutoRefresh(ctx)
1970 ar.Configure(srv.URL, jwk.WithIgnoreParseError(ignoreParseError))
1971
1972 set, err := ar.Fetch(ctx, srv.URL)
1973 if ignoreParseError {
1974 if !assert.NoError(t, err, `ar.Fetch should succeed`) {
1975 return
1976 }
1977 if !assert.Equal(t, set.Len(), 2, `JWKS should contain two keys`) {
1978 return
1979 }
1980 } else {
1981 if !assert.Error(t, err, `ar.Fetch should fail`) {
1982 return
1983 }
1984 }
1985 })
1986 }
1987
1988
1989 t.Run(`ParseKey + WithIgnoreParseError should be an error`, func(t *testing.T) {
1990 key, err := jwxtest.GenerateRsaJwk()
1991 if !assert.NoError(t, err, `jwxtest.GenerateRsaJwk() should succeed`) {
1992 return
1993 }
1994
1995 buf, err := json.Marshal(key)
1996 if !assert.NoError(t, err, `json.Marshal should succeed`) {
1997 return
1998 }
1999
2000 _, err = jwk.ParseKey(buf)
2001 if !assert.NoError(t, err, `jwk.ParseKey (no WithIgnoreParseError) should succeed`) {
2002 return
2003 }
2004
2005 _, err = jwk.ParseKey(buf, jwk.WithIgnoreParseError(true))
2006 if !assert.Error(t, err, `jwk.ParseKey (no WithIgnoreParseError) should fail`) {
2007 return
2008 }
2009 })
2010 }
2011
2012 func TestGH664(t *testing.T) {
2013 privkey, err := jwxtest.GenerateRsaKey()
2014 if !assert.NoError(t, err, `jwxtext.GenerateRsaKey() should succeed`) {
2015 return
2016 }
2017
2018 privkey.Primes = append(privkey.Primes, &big.Int{})
2019
2020 _, err = jwk.New(privkey)
2021 if !assert.Error(t, err, `jwk.New should fail`) {
2022 return
2023 }
2024
2025 privkey.Primes = privkey.Primes[:2]
2026
2027
2028 for i := 0; i < 3; i++ {
2029 i := i
2030 t.Run(fmt.Sprintf("Check what happens when primes are reduced to %d", i), func(t *testing.T) {
2031 privkey.Primes = privkey.Primes[:i]
2032 privkey.Precomputed.Dp = nil
2033 privkey.Precomputed.Dq = nil
2034 privkey.Precomputed.Qinv = nil
2035 privkey.Precomputed.CRTValues = nil
2036
2037 jwkPrivkey, err := jwk.New(privkey)
2038 if !assert.NoError(t, err, `jwk.FromRaw should succeed`) {
2039 return
2040 }
2041
2042 buf, _ := json.MarshalIndent(jwkPrivkey, "", " ")
2043 parsed, err := jwk.ParseKey(buf)
2044 if !assert.NoError(t, err, `jwk.ParseKey should succeed`) {
2045 return
2046 }
2047
2048 payload := []byte(`hello , world!`)
2049 signed, err := jws.Sign(payload, jwa.RS256, parsed)
2050 if !assert.NoError(t, err, `jws.Sign should succeed`) {
2051 return
2052 }
2053
2054 verified, err := jws.Verify(signed, jwa.RS256, privkey.PublicKey)
2055 if !assert.NoError(t, err, `jws.Verify should succeed`) {
2056 return
2057 }
2058
2059 if !assert.Equal(t, payload, verified, `verified content should match`) {
2060 return
2061 }
2062 })
2063 }
2064 }
2065
View as plain text