1/*- 2 * Copyright 2014 Square Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package jose 18 19import ( 20 "bytes" 21 "crypto" 22 "crypto/ecdsa" 23 "crypto/elliptic" 24 "crypto/rsa" 25 "crypto/x509" 26 "encoding/hex" 27 "math/big" 28 "reflect" 29 "strings" 30 "testing" 31 32 "github.com/stretchr/testify/assert" 33 "golang.org/x/crypto/ed25519" 34 35 "gopkg.in/square/go-jose.v2/json" 36) 37 38// Test chain of two X.509 certificates 39var testCertificates, _ = x509.ParseCertificates(fromBase64Bytes(` 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`)) 79 80func TestCurveSize(t *testing.T) { 81 size256 := curveSize(elliptic.P256()) 82 size384 := curveSize(elliptic.P384()) 83 size521 := curveSize(elliptic.P521()) 84 if size256 != 32 { 85 t.Error("P-256 have 32 bytes") 86 } 87 if size384 != 48 { 88 t.Error("P-384 have 48 bytes") 89 } 90 if size521 != 66 { 91 t.Error("P-521 have 66 bytes") 92 } 93} 94 95func TestRoundtripRsaPrivate(t *testing.T) { 96 jwk, err := fromRsaPrivateKey(rsaTestKey) 97 if err != nil { 98 t.Error("problem constructing JWK from rsa key", err) 99 } 100 101 rsa2, err := jwk.rsaPrivateKey() 102 if err != nil { 103 t.Error("problem converting RSA private -> JWK", err) 104 } 105 106 if rsa2.N.Cmp(rsaTestKey.N) != 0 { 107 t.Error("RSA private N mismatch") 108 } 109 if rsa2.E != rsaTestKey.E { 110 t.Error("RSA private E mismatch") 111 } 112 if rsa2.D.Cmp(rsaTestKey.D) != 0 { 113 t.Error("RSA private D mismatch") 114 } 115 if len(rsa2.Primes) != 2 { 116 t.Error("RSA private roundtrip expected two primes") 117 } 118 if rsa2.Primes[0].Cmp(rsaTestKey.Primes[0]) != 0 { 119 t.Error("RSA private P mismatch") 120 } 121 if rsa2.Primes[1].Cmp(rsaTestKey.Primes[1]) != 0 { 122 t.Error("RSA private Q mismatch") 123 } 124} 125 126func TestRoundtripRsaPrivatePrecomputed(t *testing.T) { 127 // Isolate a shallow copy of the rsaTestKey to avoid polluting it with Precompute 128 localKey := &(*rsaTestKey) 129 localKey.Precompute() 130 131 jwk, err := fromRsaPrivateKey(localKey) 132 if err != nil { 133 t.Error("problem constructing JWK from rsa key", err) 134 } 135 136 rsa2, err := jwk.rsaPrivateKey() 137 if err != nil { 138 t.Error("problem converting RSA private -> JWK", err) 139 } 140 141 if rsa2.Precomputed.Dp == nil { 142 t.Error("RSA private Dp nil") 143 } 144 if rsa2.Precomputed.Dq == nil { 145 t.Error("RSA private Dq nil") 146 } 147 if rsa2.Precomputed.Qinv == nil { 148 t.Error("RSA private Qinv nil") 149 } 150 151 if rsa2.Precomputed.Dp.Cmp(localKey.Precomputed.Dp) != 0 { 152 t.Error("RSA private Dp mismatch") 153 } 154 if rsa2.Precomputed.Dq.Cmp(localKey.Precomputed.Dq) != 0 { 155 t.Error("RSA private Dq mismatch") 156 } 157 if rsa2.Precomputed.Qinv.Cmp(localKey.Precomputed.Qinv) != 0 { 158 t.Error("RSA private Qinv mismatch") 159 } 160} 161 162func TestRsaPrivateInsufficientPrimes(t *testing.T) { 163 brokenRsaPrivateKey := rsa.PrivateKey{ 164 PublicKey: rsa.PublicKey{ 165 N: rsaTestKey.N, 166 E: rsaTestKey.E, 167 }, 168 D: rsaTestKey.D, 169 Primes: []*big.Int{rsaTestKey.Primes[0]}, 170 } 171 172 _, err := fromRsaPrivateKey(&brokenRsaPrivateKey) 173 if err != ErrUnsupportedKeyType { 174 t.Error("expected unsupported key type error, got", err) 175 } 176} 177 178func TestRsaPrivateExcessPrimes(t *testing.T) { 179 brokenRsaPrivateKey := rsa.PrivateKey{ 180 PublicKey: rsa.PublicKey{ 181 N: rsaTestKey.N, 182 E: rsaTestKey.E, 183 }, 184 D: rsaTestKey.D, 185 Primes: []*big.Int{ 186 rsaTestKey.Primes[0], 187 rsaTestKey.Primes[1], 188 big.NewInt(3), 189 }, 190 } 191 192 _, err := fromRsaPrivateKey(&brokenRsaPrivateKey) 193 if err != ErrUnsupportedKeyType { 194 t.Error("expected unsupported key type error, got", err) 195 } 196} 197 198func TestRoundtripEcPublic(t *testing.T) { 199 for i, ecTestKey := range []*ecdsa.PrivateKey{ecTestKey256, ecTestKey384, ecTestKey521} { 200 jwk, err := fromEcPublicKey(&ecTestKey.PublicKey) 201 202 ec2, err := jwk.ecPublicKey() 203 if err != nil { 204 t.Error("problem converting ECDSA private -> JWK", i, err) 205 } 206 207 if !reflect.DeepEqual(ec2.Curve, ecTestKey.Curve) { 208 t.Error("ECDSA private curve mismatch", i) 209 } 210 if ec2.X.Cmp(ecTestKey.X) != 0 { 211 t.Error("ECDSA X mismatch", i) 212 } 213 if ec2.Y.Cmp(ecTestKey.Y) != 0 { 214 t.Error("ECDSA Y mismatch", i) 215 } 216 } 217} 218 219func TestRoundtripEcPrivate(t *testing.T) { 220 for i, ecTestKey := range []*ecdsa.PrivateKey{ecTestKey256, ecTestKey384, ecTestKey521} { 221 jwk, err := fromEcPrivateKey(ecTestKey) 222 223 ec2, err := jwk.ecPrivateKey() 224 if err != nil { 225 t.Fatalf("problem converting ECDSA private -> JWK for %#v: %s", ecTestKey, err) 226 } 227 228 if !reflect.DeepEqual(ec2.Curve, ecTestKey.Curve) { 229 t.Error("ECDSA private curve mismatch", i) 230 } 231 if ec2.X.Cmp(ecTestKey.X) != 0 { 232 t.Error("ECDSA X mismatch", i) 233 } 234 if ec2.Y.Cmp(ecTestKey.Y) != 0 { 235 t.Error("ECDSA Y mismatch", i) 236 } 237 if ec2.D.Cmp(ecTestKey.D) != 0 { 238 t.Error("ECDSA D mismatch", i) 239 } 240 } 241} 242 243func TestRoundtripX5C(t *testing.T) { 244 jwk := JSONWebKey{ 245 Key: rsaTestKey, 246 KeyID: "bar", 247 Algorithm: "foo", 248 Certificates: testCertificates, 249 } 250 251 jsonbar, err := jwk.MarshalJSON() 252 if err != nil { 253 t.Error("problem marshaling", err) 254 } 255 256 var jwk2 JSONWebKey 257 err = jwk2.UnmarshalJSON(jsonbar) 258 if err != nil { 259 t.Fatal("problem unmarshalling", err) 260 } 261 262 if !reflect.DeepEqual(testCertificates, jwk2.Certificates) { 263 t.Error("Certificates not equal", jwk.Certificates, jwk2.Certificates) 264 } 265 266 jsonbar2, err := jwk2.MarshalJSON() 267 if err != nil { 268 t.Error("problem marshaling", err) 269 } 270 if !bytes.Equal(jsonbar, jsonbar2) { 271 t.Error("roundtrip should not lose information") 272 } 273} 274 275func TestMarshalUnmarshal(t *testing.T) { 276 kid := "DEADBEEF" 277 278 for i, key := range []interface{}{ecTestKey256, ecTestKey384, ecTestKey521, rsaTestKey, ed25519PrivateKey} { 279 for _, use := range []string{"", "sig", "enc"} { 280 jwk := JSONWebKey{Key: key, KeyID: kid, Algorithm: "foo"} 281 if use != "" { 282 jwk.Use = use 283 } 284 285 jsonbar, err := jwk.MarshalJSON() 286 if err != nil { 287 t.Error("problem marshaling", i, err) 288 } 289 290 var jwk2 JSONWebKey 291 err = jwk2.UnmarshalJSON(jsonbar) 292 if err != nil { 293 t.Fatal("problem unmarshalling", i, err) 294 } 295 296 jsonbar2, err := jwk2.MarshalJSON() 297 if err != nil { 298 t.Fatal("problem marshaling", i, err) 299 } 300 301 if !bytes.Equal(jsonbar, jsonbar2) { 302 t.Error("roundtrip should not lose information", i) 303 } 304 if jwk2.KeyID != kid { 305 t.Error("kid did not roundtrip JSON marshalling", i) 306 } 307 308 if jwk2.Algorithm != "foo" { 309 t.Error("alg did not roundtrip JSON marshalling", i) 310 } 311 312 if jwk2.Use != use { 313 t.Error("use did not roundtrip JSON marshalling", i) 314 } 315 } 316 } 317} 318 319func TestMarshalNonPointer(t *testing.T) { 320 type EmbedsKey struct { 321 Key JSONWebKey 322 } 323 324 keyJSON := []byte(`{ 325 "e": "AQAB", 326 "kty": "RSA", 327 "n": "vd7rZIoTLEe-z1_8G1FcXSw9CQFEJgV4g9V277sER7yx5Qjz_Pkf2YVth6wwwFJEmzc0hoKY-MMYFNwBE4hQHw" 328 }`) 329 var parsedKey JSONWebKey 330 err := json.Unmarshal(keyJSON, &parsedKey) 331 if err != nil { 332 t.Errorf("Error unmarshalling key: %v", err) 333 return 334 } 335 ek := EmbedsKey{ 336 Key: parsedKey, 337 } 338 out, err := json.Marshal(ek) 339 if err != nil { 340 t.Errorf("Error marshalling JSON: %v", err) 341 return 342 } 343 expected := "{\"Key\":{\"kty\":\"RSA\",\"n\":\"vd7rZIoTLEe-z1_8G1FcXSw9CQFEJgV4g9V277sER7yx5Qjz_Pkf2YVth6wwwFJEmzc0hoKY-MMYFNwBE4hQHw\",\"e\":\"AQAB\"}}" 344 if string(out) != expected { 345 t.Error("Failed to marshal embedded non-pointer JWK properly:", string(out)) 346 } 347} 348 349func TestMarshalUnmarshalInvalid(t *testing.T) { 350 // Make an invalid curve coordinate by creating a byte array that is one 351 // byte too large, and setting the first byte to 1 (otherwise it's just zero). 352 invalidCoord := make([]byte, curveSize(ecTestKey256.Curve)+1) 353 invalidCoord[0] = 1 354 355 keys := []interface{}{ 356 // Empty keys 357 &rsa.PrivateKey{}, 358 &ecdsa.PrivateKey{}, 359 // Invalid keys 360 &ecdsa.PrivateKey{ 361 PublicKey: ecdsa.PublicKey{ 362 // Missing values in pub key 363 Curve: elliptic.P256(), 364 }, 365 }, 366 &ecdsa.PrivateKey{ 367 PublicKey: ecdsa.PublicKey{ 368 // Invalid curve 369 Curve: nil, 370 X: ecTestKey256.X, 371 Y: ecTestKey256.Y, 372 }, 373 }, 374 &ecdsa.PrivateKey{ 375 // Valid pub key, but missing priv key values 376 PublicKey: ecTestKey256.PublicKey, 377 }, 378 &ecdsa.PrivateKey{ 379 // Invalid pub key, values too large 380 PublicKey: ecdsa.PublicKey{ 381 Curve: ecTestKey256.Curve, 382 X: big.NewInt(0).SetBytes(invalidCoord), 383 Y: big.NewInt(0).SetBytes(invalidCoord), 384 }, 385 D: ecTestKey256.D, 386 }, 387 nil, 388 } 389 390 for i, key := range keys { 391 jwk := JSONWebKey{Key: key} 392 _, err := jwk.MarshalJSON() 393 if err == nil { 394 t.Error("managed to serialize invalid key", i) 395 } 396 } 397} 398 399func TestWebKeyVectorsInvalid(t *testing.T) { 400 keys := []string{ 401 // Invalid JSON 402 "{X", 403 // Empty key 404 "{}", 405 // Invalid RSA keys 406 `{"kty":"RSA"}`, 407 `{"kty":"RSA","e":""}`, 408 `{"kty":"RSA","e":"XXXX"}`, 409 `{"kty":"RSA","d":"XXXX"}`, 410 // Invalid EC keys 411 `{"kty":"EC","crv":"ABC"}`, 412 `{"kty":"EC","crv":"P-256"}`, 413 `{"kty":"EC","crv":"P-256","d":"XXX"}`, 414 `{"kty":"EC","crv":"ABC","d":"dGVzdA","x":"dGVzdA"}`, 415 `{"kty":"EC","crv":"P-256","d":"dGVzdA","x":"dGVzdA"}`, 416 } 417 418 for _, key := range keys { 419 var jwk2 JSONWebKey 420 err := jwk2.UnmarshalJSON([]byte(key)) 421 if err == nil { 422 t.Error("managed to parse invalid key:", key) 423 } 424 } 425} 426 427// Test vectors from RFC 7520 428var cookbookJWKs = []string{ 429 // EC Public 430 stripWhitespace(`{ 431 "kty": "EC", 432 "kid": "bilbo.baggins@hobbiton.example", 433 "use": "sig", 434 "crv": "P-521", 435 "x": "AHKZLLOsCOzz5cY97ewNUajB957y-C-U88c3v13nmGZx6sYl_oJXu9 436 A5RkTKqjqvjyekWF-7ytDyRXYgCF5cj0Kt", 437 "y": "AdymlHvOiLxXkEhayXQnNCvDX4h9htZaCJN34kfmC6pV5OhQHiraVy 438 SsUdaQkAgDPrwQrJmbnX9cwlGfP-HqHZR1" 439 }`), 440 441 //ED Private 442 stripWhitespace(`{ 443 "kty": "OKP", 444 "crv": "Ed25519", 445 "x": "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo", 446 "d": "nWGxne_9WmC6hEr0kuwsxERJxWl7MmkZcDusAxyuf2A" 447 }`), 448 449 // EC Private 450 stripWhitespace(`{ 451 "kty": "EC", 452 "kid": "bilbo.baggins@hobbiton.example", 453 "use": "sig", 454 "crv": "P-521", 455 "x": "AHKZLLOsCOzz5cY97ewNUajB957y-C-U88c3v13nmGZx6sYl_oJXu9 456 A5RkTKqjqvjyekWF-7ytDyRXYgCF5cj0Kt", 457 "y": "AdymlHvOiLxXkEhayXQnNCvDX4h9htZaCJN34kfmC6pV5OhQHiraVy 458 SsUdaQkAgDPrwQrJmbnX9cwlGfP-HqHZR1", 459 "d": "AAhRON2r9cqXX1hg-RoI6R1tX5p2rUAYdmpHZoC1XNM56KtscrX6zb 460 KipQrCW9CGZH3T4ubpnoTKLDYJ_fF3_rJt" 461 }`), 462 463 // RSA Public 464 stripWhitespace(`{ 465 "kty": "RSA", 466 "kid": "bilbo.baggins@hobbiton.example", 467 "use": "sig", 468 "n": "n4EPtAOCc9AlkeQHPzHStgAbgs7bTZLwUBZdR8_KuKPEHLd4rHVTeT 469 -O-XV2jRojdNhxJWTDvNd7nqQ0VEiZQHz_AJmSCpMaJMRBSFKrKb2wqV 470 wGU_NsYOYL-QtiWN2lbzcEe6XC0dApr5ydQLrHqkHHig3RBordaZ6Aj- 471 oBHqFEHYpPe7Tpe-OfVfHd1E6cS6M1FZcD1NNLYD5lFHpPI9bTwJlsde 472 3uhGqC0ZCuEHg8lhzwOHrtIQbS0FVbb9k3-tVTU4fg_3L_vniUFAKwuC 473 LqKnS2BYwdq_mzSnbLY7h_qixoR7jig3__kRhuaxwUkRz5iaiQkqgc5g 474 HdrNP5zw", 475 "e": "AQAB" 476 }`), 477 478 // RSA Private 479 stripWhitespace(`{"kty":"RSA", 480 "kid":"juliet@capulet.lit", 481 "use":"enc", 482 "n":"t6Q8PWSi1dkJj9hTP8hNYFlvadM7DflW9mWepOJhJ66w7nyoK1gPNqFMSQRy 483 O125Gp-TEkodhWr0iujjHVx7BcV0llS4w5ACGgPrcAd6ZcSR0-Iqom-QFcNP 484 8Sjg086MwoqQU_LYywlAGZ21WSdS_PERyGFiNnj3QQlO8Yns5jCtLCRwLHL0 485 Pb1fEv45AuRIuUfVcPySBWYnDyGxvjYGDSM-AqWS9zIQ2ZilgT-GqUmipg0X 486 OC0Cc20rgLe2ymLHjpHciCKVAbY5-L32-lSeZO-Os6U15_aXrk9Gw8cPUaX1 487 _I8sLGuSiVdt3C_Fn2PZ3Z8i744FPFGGcG1qs2Wz-Q", 488 "e":"AQAB", 489 "d":"GRtbIQmhOZtyszfgKdg4u_N-R_mZGU_9k7JQ_jn1DnfTuMdSNprTeaSTyWfS 490 NkuaAwnOEbIQVy1IQbWVV25NY3ybc_IhUJtfri7bAXYEReWaCl3hdlPKXy9U 491 vqPYGR0kIXTQRqns-dVJ7jahlI7LyckrpTmrM8dWBo4_PMaenNnPiQgO0xnu 492 ToxutRZJfJvG4Ox4ka3GORQd9CsCZ2vsUDmsXOfUENOyMqADC6p1M3h33tsu 493 rY15k9qMSpG9OX_IJAXmxzAh_tWiZOwk2K4yxH9tS3Lq1yX8C1EWmeRDkK2a 494 hecG85-oLKQt5VEpWHKmjOi_gJSdSgqcN96X52esAQ", 495 "p":"2rnSOV4hKSN8sS4CgcQHFbs08XboFDqKum3sc4h3GRxrTmQdl1ZK9uw-PIHf 496 QP0FkxXVrx-WE-ZEbrqivH_2iCLUS7wAl6XvARt1KkIaUxPPSYB9yk31s0Q8 497 UK96E3_OrADAYtAJs-M3JxCLfNgqh56HDnETTQhH3rCT5T3yJws", 498 "q":"1u_RiFDP7LBYh3N4GXLT9OpSKYP0uQZyiaZwBtOCBNJgQxaj10RWjsZu0c6I 499 edis4S7B_coSKB0Kj9PaPaBzg-IySRvvcQuPamQu66riMhjVtG6TlV8CLCYK 500 rYl52ziqK0E_ym2QnkwsUX7eYTB7LbAHRK9GqocDE5B0f808I4s", 501 "dp":"KkMTWqBUefVwZ2_Dbj1pPQqyHSHjj90L5x_MOzqYAJMcLMZtbUtwKqvVDq3 502 tbEo3ZIcohbDtt6SbfmWzggabpQxNxuBpoOOf_a_HgMXK_lhqigI4y_kqS1w 503 Y52IwjUn5rgRrJ-yYo1h41KR-vz2pYhEAeYrhttWtxVqLCRViD6c", 504 "dq":"AvfS0-gRxvn0bwJoMSnFxYcK1WnuEjQFluMGfwGitQBWtfZ1Er7t1xDkbN9 505 GQTB9yqpDoYaN06H7CFtrkxhJIBQaj6nkF5KKS3TQtQ5qCzkOkmxIe3KRbBy 506 mXxkb5qwUpX5ELD5xFc6FeiafWYY63TmmEAu_lRFCOJ3xDea-ots", 507 "qi":"lSQi-w9CpyUReMErP1RsBLk7wNtOvs5EQpPqmuMvqW57NBUczScEoPwmUqq 508 abu9V0-Py4dQ57_bapoKRu1R90bvuFnU63SHWEFglZQvJDMeAvmj4sm-Fp0o 509 Yu_neotgQ0hzbI5gry7ajdYy9-2lNx_76aBZoOUu9HCJ-UsfSOI8"}`), 510 511 // X.509 Certificate Chain 512 stripWhitespace(`{"kty":"RSA", 513 "use":"sig", 514 "kid":"1b94c", 515 "n":"vrjOfz9Ccdgx5nQudyhdoR17V-IubWMeOZCwX_jj0hgAsz2J_pqYW08 516 PLbK_PdiVGKPrqzmDIsLI7sA25VEnHU1uCLNwBuUiCO11_-7dYbsr4iJmG0Q 517 u2j8DsVyT1azpJC_NG84Ty5KKthuCaPod7iI7w0LK9orSMhBEwwZDCxTWq4a 518 YWAchc8t-emd9qOvWtVMDC2BXksRngh6X5bUYLy6AyHKvj-nUy1wgzjYQDwH 519 MTplCoLtU-o-8SNnZ1tmRoGE9uJkBLdh5gFENabWnU5m1ZqZPdwS-qo-meMv 520 VfJb6jJVWRpl2SUtCnYG2C32qvbWbjZ_jBPD5eunqsIo1vQ", 521 "e":"AQAB", 522 "x5c": 523 ["MIIDQjCCAiqgAwIBAgIGATz/FuLiMA0GCSqGSIb3DQEBBQUAMGIxCzAJB 524 gNVBAYTAlVTMQswCQYDVQQIEwJDTzEPMA0GA1UEBxMGRGVudmVyMRwwGgYD 525 VQQKExNQaW5nIElkZW50aXR5IENvcnAuMRcwFQYDVQQDEw5CcmlhbiBDYW1 526 wYmVsbDAeFw0xMzAyMjEyMzI5MTVaFw0xODA4MTQyMjI5MTVaMGIxCzAJBg 527 NVBAYTAlVTMQswCQYDVQQIEwJDTzEPMA0GA1UEBxMGRGVudmVyMRwwGgYDV 528 QQKExNQaW5nIElkZW50aXR5IENvcnAuMRcwFQYDVQQDEw5CcmlhbiBDYW1w 529 YmVsbDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL64zn8/QnH 530 YMeZ0LncoXaEde1fiLm1jHjmQsF/449IYALM9if6amFtPDy2yvz3YlRij66 531 s5gyLCyO7ANuVRJx1NbgizcAblIgjtdf/u3WG7K+IiZhtELto/A7Fck9Ws6 532 SQvzRvOE8uSirYbgmj6He4iO8NCyvaK0jIQRMMGQwsU1quGmFgHIXPLfnpn 533 fajr1rVTAwtgV5LEZ4Iel+W1GC8ugMhyr4/p1MtcIM42EA8BzE6ZQqC7VPq 534 PvEjZ2dbZkaBhPbiZAS3YeYBRDWm1p1OZtWamT3cEvqqPpnjL1XyW+oyVVk 535 aZdklLQp2Btgt9qr21m42f4wTw+Xrp6rCKNb0CAwEAATANBgkqhkiG9w0BA 536 QUFAAOCAQEAh8zGlfSlcI0o3rYDPBB07aXNswb4ECNIKG0CETTUxmXl9KUL 537 +9gGlqCz5iWLOgWsnrcKcY0vXPG9J1r9AqBNTqNgHq2G03X09266X5CpOe1 538 zFo+Owb1zxtp3PehFdfQJ610CDLEaS9V9Rqp17hCyybEpOGVwe8fnk+fbEL 539 2Bo3UPGrpsHzUoaGpDftmWssZkhpBJKVMJyf/RuP2SmmaIzmnw9JiSlYhzo 540 4tpzd5rFXhjRbg4zW9C+2qok+2+qDM1iJ684gPHMIY8aLWrdgQTxkumGmTq 541 gawR+N5MDtdPTEQ0XfIBc2cJEUyMTY5MPvACWpkA6SdS4xSvdXK3IVfOWA=="]}`), 542} 543 544// SHA-256 thumbprints of the above keys, hex-encoded 545var cookbookJWKThumbprints = []string{ 546 "747ae2dd2003664aeeb21e4753fe7402846170a16bc8df8f23a8cf06d3cbe793", 547 "f6934029a341ddf81dceb753e91d17efe16664f40d9f4ed84bc5ea87e111f29d", 548 "747ae2dd2003664aeeb21e4753fe7402846170a16bc8df8f23a8cf06d3cbe793", 549 "f63838e96077ad1fc01c3f8405774dedc0641f558ebb4b40dccf5f9b6d66a932", 550 "0fc478f8579325fcee0d4cbc6d9d1ce21730a6e97e435d6008fb379b0ebe47d4", 551 "0ddb05bfedbec2070fa037324ba397396561d3425d6d69245570c261dc49dee3", 552} 553 554func TestWebKeyVectorsValid(t *testing.T) { 555 for _, key := range cookbookJWKs { 556 var jwk2 JSONWebKey 557 err := jwk2.UnmarshalJSON([]byte(key)) 558 if err != nil { 559 t.Error("unable to parse valid key:", key, err) 560 } 561 } 562} 563 564func TestEd25519Serialization(t *testing.T) { 565 jwk := JSONWebKey{ 566 Key: ed25519PrivateKey, 567 } 568 serialized, _ := json.Marshal(jwk) 569 570 var jwk2 JSONWebKey 571 json.Unmarshal(serialized, &jwk2) 572 573 assert.True(t, bytes.Equal( 574 []byte(jwk.Key.(ed25519.PrivateKey).Public().(ed25519.PublicKey)), 575 []byte(jwk2.Key.(ed25519.PrivateKey).Public().(ed25519.PublicKey)))) 576} 577 578func TestThumbprint(t *testing.T) { 579 for i, key := range cookbookJWKs { 580 var jwk2 JSONWebKey 581 err := jwk2.UnmarshalJSON([]byte(key)) 582 if err != nil { 583 t.Error("unable to parse valid key:", key, err) 584 } 585 586 tp, err := jwk2.Thumbprint(crypto.SHA256) 587 if err != nil { 588 t.Error("unable to compute thumbprint:", key, err) 589 } 590 591 tpHex := hex.EncodeToString(tp) 592 if cookbookJWKThumbprints[i] != tpHex { 593 t.Error("incorrect thumbprint:", i, cookbookJWKThumbprints[i], tpHex) 594 } 595 } 596} 597 598func TestMarshalUnmarshalJWKSet(t *testing.T) { 599 jwk1 := JSONWebKey{Key: rsaTestKey, KeyID: "ABCDEFG", Algorithm: "foo"} 600 jwk2 := JSONWebKey{Key: rsaTestKey, KeyID: "GFEDCBA", Algorithm: "foo"} 601 var set JSONWebKeySet 602 set.Keys = append(set.Keys, jwk1) 603 set.Keys = append(set.Keys, jwk2) 604 605 jsonbar, err := json.Marshal(&set) 606 if err != nil { 607 t.Error("problem marshalling set", err) 608 } 609 var set2 JSONWebKeySet 610 err = json.Unmarshal(jsonbar, &set2) 611 if err != nil { 612 t.Fatal("problem unmarshalling set", err) 613 } 614 jsonbar2, err := json.Marshal(&set2) 615 if err != nil { 616 t.Fatal("problem marshalling set", err) 617 } 618 if !bytes.Equal(jsonbar, jsonbar2) { 619 t.Error("roundtrip should not lose information") 620 } 621} 622 623func TestJWKSetKey(t *testing.T) { 624 jwk1 := JSONWebKey{Key: rsaTestKey, KeyID: "ABCDEFG", Algorithm: "foo"} 625 jwk2 := JSONWebKey{Key: rsaTestKey, KeyID: "GFEDCBA", Algorithm: "foo"} 626 var set JSONWebKeySet 627 set.Keys = append(set.Keys, jwk1) 628 set.Keys = append(set.Keys, jwk2) 629 k := set.Key("ABCDEFG") 630 if len(k) != 1 { 631 t.Errorf("method should return slice with one key not %d", len(k)) 632 } 633 if k[0].KeyID != "ABCDEFG" { 634 t.Error("method should return key with ID ABCDEFG") 635 } 636} 637 638func TestJWKSymmetricKey(t *testing.T) { 639 sample1 := `{"kty":"oct","alg":"A128KW","k":"GawgguFyGrWKav7AX4VKUg"}` 640 sample2 := `{"kty":"oct","k":"AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow","kid":"HMAC key used in JWS spec Appendix A.1 example"}` 641 642 var jwk1 JSONWebKey 643 json.Unmarshal([]byte(sample1), &jwk1) 644 645 if jwk1.Algorithm != "A128KW" { 646 t.Errorf("expected Algorithm to be A128KW, but was '%s'", jwk1.Algorithm) 647 } 648 expected1 := fromHexBytes("19ac2082e1721ab58a6afec05f854a52") 649 if !bytes.Equal(jwk1.Key.([]byte), expected1) { 650 t.Errorf("expected Key to be '%s', but was '%s'", hex.EncodeToString(expected1), hex.EncodeToString(jwk1.Key.([]byte))) 651 } 652 653 var jwk2 JSONWebKey 654 json.Unmarshal([]byte(sample2), &jwk2) 655 656 if jwk2.KeyID != "HMAC key used in JWS spec Appendix A.1 example" { 657 t.Errorf("expected KeyID to be 'HMAC key used in JWS spec Appendix A.1 example', but was '%s'", jwk2.KeyID) 658 } 659 expected2 := fromHexBytes(` 660 0323354b2b0fa5bc837e0665777ba68f5ab328e6f054c928a90f84b2d2502ebf 661 d3fb5a92d20647ef968ab4c377623d223d2e2172052e4f08c0cd9af567d080a3`) 662 if !bytes.Equal(jwk2.Key.([]byte), expected2) { 663 t.Errorf("expected Key to be '%s', but was '%s'", hex.EncodeToString(expected2), hex.EncodeToString(jwk2.Key.([]byte))) 664 } 665} 666 667func TestJWKSymmetricRoundtrip(t *testing.T) { 668 jwk1 := JSONWebKey{Key: []byte{1, 2, 3, 4}} 669 marshaled, err := jwk1.MarshalJSON() 670 if err != nil { 671 t.Error("failed to marshal valid JWK object", err) 672 } 673 674 var jwk2 JSONWebKey 675 err = jwk2.UnmarshalJSON(marshaled) 676 if err != nil { 677 t.Error("failed to unmarshal valid JWK object", err) 678 } 679 680 if !bytes.Equal(jwk1.Key.([]byte), jwk2.Key.([]byte)) { 681 t.Error("round-trip of symmetric JWK gave different raw keys") 682 } 683} 684 685func TestJWKSymmetricInvalid(t *testing.T) { 686 invalid := JSONWebKey{} 687 _, err := invalid.MarshalJSON() 688 if err == nil { 689 t.Error("excepted error on marshaling invalid symmetric JWK object") 690 } 691 692 var jwk JSONWebKey 693 err = jwk.UnmarshalJSON([]byte(`{"kty":"oct"}`)) 694 if err == nil { 695 t.Error("excepted error on unmarshaling invalid symmetric JWK object") 696 } 697} 698 699func TestJWKIsPublic(t *testing.T) { 700 bigInt := big.NewInt(0) 701 eccPub := ecdsa.PublicKey{elliptic.P256(), bigInt, bigInt} 702 rsaPub := rsa.PublicKey{bigInt, 1} 703 704 cases := []struct { 705 key interface{} 706 expectedIsPublic bool 707 }{ 708 {&eccPub, true}, 709 {&ecdsa.PrivateKey{eccPub, bigInt}, false}, 710 {&rsaPub, true}, 711 {&rsa.PrivateKey{rsaPub, bigInt, []*big.Int{bigInt, bigInt}, rsa.PrecomputedValues{}}, false}, 712 {ed25519PublicKey, true}, 713 {ed25519PrivateKey, false}, 714 } 715 716 for _, tc := range cases { 717 k := &JSONWebKey{Key: tc.key} 718 if public := k.IsPublic(); public != tc.expectedIsPublic { 719 t.Errorf("expected IsPublic to return %t, got %t", tc.expectedIsPublic, public) 720 } 721 } 722} 723 724func TestJWKValid(t *testing.T) { 725 bigInt := big.NewInt(0) 726 eccPub := ecdsa.PublicKey{elliptic.P256(), bigInt, bigInt} 727 rsaPub := rsa.PublicKey{bigInt, 1} 728 edPubEmpty := ed25519.PublicKey([]byte{}) 729 edPrivEmpty := ed25519.PublicKey([]byte{}) 730 731 cases := []struct { 732 key interface{} 733 expectedValidity bool 734 }{ 735 {nil, false}, 736 {&ecdsa.PublicKey{}, false}, 737 {&eccPub, true}, 738 {&ecdsa.PrivateKey{}, false}, 739 {&ecdsa.PrivateKey{eccPub, bigInt}, true}, 740 {&rsa.PublicKey{}, false}, 741 {&rsaPub, true}, 742 {&rsa.PrivateKey{}, false}, 743 {&rsa.PrivateKey{rsaPub, bigInt, []*big.Int{bigInt, bigInt}, rsa.PrecomputedValues{}}, true}, 744 {ed25519PublicKey, true}, 745 {ed25519PrivateKey, true}, 746 {edPubEmpty, false}, 747 {edPrivEmpty, false}, 748 } 749 750 for _, tc := range cases { 751 k := &JSONWebKey{Key: tc.key} 752 valid := k.Valid() 753 if valid != tc.expectedValidity { 754 t.Errorf("expected Valid to return %t, got %t", tc.expectedValidity, valid) 755 } 756 if valid { 757 wasPublic := k.IsPublic() 758 p := k.Public() // all aforemention keys are asymmetric 759 if !p.Valid() { 760 t.Errorf("unable to derive public key from valid asymmetric key") 761 } 762 if wasPublic != k.IsPublic() { 763 t.Errorf("original key was touched during public key derivation") 764 } 765 } 766 } 767} 768 769func TestJWKBufferSizeCheck(t *testing.T) { 770 key := `{ 771 "kty":"EC", 772 "crv":"P-256", 773 "x":"m9GSmJ5iGmAYlMlaOJGSFN_CjN9cIn8GGYExP-C0FBiIXlWTNvGN38R9WdrHcppfsKF0FXMOMyutpHIRaiMxYSA", 774 "y":"ZaPcRZ3q_7T3h-Gwz2i-T2JjJXfj6YVGgKHcFz5zqmg"}` 775 var jwk JSONWebKey 776 jwk.UnmarshalJSON([]byte(key)) 777 jwk.Valid() // true 778 // panic: square/go-jose: invalid call to newFixedSizeBuffer (len(data) > length) 779 // github.com/square/go-jose.newFixedSizeBuffer(0xc420014557, 0x41, 0x41, 0x20, 0x0) 780 jwk.Thumbprint(crypto.SHA256) 781} 782 783func TestJWKPaddingPrivateX(t *testing.T) { 784 key := `{ 785 "kty": "EC", 786 "crv": "P-256", 787 "x": "nPTIABcDASY6FNGSNfHCB51tY7qChtgzeVazOtLrwQ", 788 "y": "vEEs4V0egJkNyM2Q4pp001zu14VcpQ0_Ei8xOOPxKZs", 789 "d": "nIVCvMR2wkLmeGJErOpI23VDHl2s3JwGdbzKy0odir0" 790 }` 791 var jwk JSONWebKey 792 err := jwk.UnmarshalJSON([]byte(key)) 793 if err == nil { 794 t.Errorf("Expected key with short x to fail unmarshalling") 795 } 796 if !strings.Contains(err.Error(), "wrong length for x") { 797 t.Errorf("Wrong error for short x, got %q", err) 798 } 799 if jwk.Valid() { 800 t.Errorf("Expected key to be invalid, but it was valid.") 801 } 802} 803 804func TestJWKPaddingPrivateY(t *testing.T) { 805 key := `{ 806 "kty": "EC", 807 "crv": "P-256", 808 "x": "vEEs4V0egJkNyM2Q4pp001zu14VcpQ0_Ei8xOOPxKZs", 809 "y": "nPTIABcDASY6FNGSNfHCB51tY7qChtgzeVazOtLrwQ", 810 "d": "nIVCvMR2wkLmeGJErOpI23VDHl2s3JwGdbzKy0odir0" 811 }` 812 var jwk JSONWebKey 813 err := jwk.UnmarshalJSON([]byte(key)) 814 if err == nil { 815 t.Errorf("Expected key with short x to fail unmarshalling") 816 } 817 if !strings.Contains(err.Error(), "wrong length for y") { 818 t.Errorf("Wrong error for short y, got %q", err) 819 } 820 if jwk.Valid() { 821 t.Errorf("Expected key to be invalid, but it was valid.") 822 } 823} 824 825func TestJWKPaddingPrivateD(t *testing.T) { 826 key := `{ 827 "kty": "EC", 828 "crv": "P-256", 829 "x": "vEEs4V0egJkNyM2Q4pp001zu14VcpQ0_Ei8xOOPxKZs", 830 "y": "qnPTIABcDASY6FNGSNfHCB51tY7qChtgzeVazOtLrwQ", 831 "d": "IVCvMR2wkLmeGJErOpI23VDHl2s3JwGdbzKy0odir0" 832 }` 833 var jwk JSONWebKey 834 err := jwk.UnmarshalJSON([]byte(key)) 835 if err == nil { 836 t.Errorf("Expected key with short x to fail unmarshalling") 837 } 838 if !strings.Contains(err.Error(), "wrong length for d") { 839 t.Errorf("Wrong error for short d, got %q", err) 840 } 841 if jwk.Valid() { 842 t.Errorf("Expected key to be invalid, but it was valid.") 843 } 844} 845 846func TestJWKPaddingX(t *testing.T) { 847 key := `{ 848 "kty": "EC", 849 "crv": "P-256", 850 "x": "nPTIABcDASY6FNGSNfHCB51tY7qChtgzeVazOtLrwQ", 851 "y": "vEEs4V0egJkNyM2Q4pp001zu14VcpQ0_Ei8xOOPxKZs" 852 }` 853 var jwk JSONWebKey 854 err := jwk.UnmarshalJSON([]byte(key)) 855 if err == nil { 856 t.Errorf("Expected key with short x to fail unmarshalling") 857 } 858 if !strings.Contains(err.Error(), "wrong length for x") { 859 t.Errorf("Wrong error for short x, got %q", err) 860 } 861 if jwk.Valid() { 862 t.Errorf("Expected key to be invalid, but it was valid.") 863 } 864} 865 866func TestJWKPaddingY(t *testing.T) { 867 key := `{ 868 "kty": "EC", 869 "crv": "P-256", 870 "x": "vEEs4V0egJkNyM2Q4pp001zu14VcpQ0_Ei8xOOPxKZs", 871 "y": "nPTIABcDASY6FNGSNfHCB51tY7qChtgzeVazOtLrwQ" 872 }` 873 var jwk JSONWebKey 874 err := jwk.UnmarshalJSON([]byte(key)) 875 if err == nil { 876 t.Errorf("Expected key with short y to fail unmarshalling") 877 } 878 if !strings.Contains(err.Error(), "wrong length for y") { 879 t.Errorf("Wrong error for short y, got %q", err) 880 } 881 if jwk.Valid() { 882 t.Errorf("Expected key to be invalid, but it was valid.") 883 } 884} 885