github.com/trustbloc/kms-go@v1.1.2/doc/jose/jwk/jwksupport/jwk_test.go (about) 1 /* 2 Copyright SecureKey Technologies Inc. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package jwksupport 8 9 import ( 10 "crypto/ecdsa" 11 "crypto/ed25519" 12 "crypto/elliptic" 13 "crypto/rand" 14 "crypto/rsa" 15 "crypto/sha256" 16 "crypto/x509" 17 "crypto/x509/pkix" 18 "encoding/asn1" 19 "encoding/base64" 20 "encoding/json" 21 "fmt" 22 "strings" 23 "testing" 24 25 "github.com/btcsuite/btcd/btcec/v2" 26 "github.com/go-jose/go-jose/v3" 27 "github.com/stretchr/testify/require" 28 "github.com/trustbloc/bbs-signature-go/bbs12381g2pub" 29 30 "github.com/trustbloc/kms-go/doc/jose/jwk" 31 cryptoapi "github.com/trustbloc/kms-go/spi/crypto" 32 "github.com/trustbloc/kms-go/spi/kms" 33 "github.com/trustbloc/kms-go/util/cryptoutil" 34 ) 35 36 func TestDecodeJWK(t *testing.T) { 37 t.Run("Test decode public key success", func(t *testing.T) { 38 tests := []struct { 39 name string 40 jwkJSON string 41 }{ 42 { 43 name: "get public key bytes Ed25519 JWK", 44 jwkJSON: `{ 45 "kty": "OKP", 46 "use": "enc", 47 "crv": "Ed25519", 48 "kid": "sample@sample.id", 49 "x": "sEHL6KXs8bUz9Ss2qSWWjhhRMHVjrog0lzFENM132R8", 50 "alg": "EdDSA" 51 }`, 52 }, 53 { 54 name: "get public key bytes X25519 JWK", 55 jwkJSON: `{ 56 "kty": "OKP", 57 "use": "enc", 58 "crv": "X25519", 59 "kid": "sample@sample.id", 60 "x": "sEHL6KXs8bUz9Ss2qSWWjhhRMHVjrog0lzFENM132R8" 61 }`, 62 }, 63 { 64 name: "get public key bytes BBS+ JWK", 65 //nolint:lll 66 jwkJSON: `{ 67 "kty": "EC", 68 "use": "enc", 69 "crv": "BLS12381_G2", 70 "kid": "sample@sample.id", 71 "x": "tKWJu0SOY7onl4tEyOOH11XBriQN2JgzV-UmjgBMSsNkcAx3_l97SVYViSDBouTVBkBfrLh33C5icDD-4UEDxNO3Wn1ijMHvn2N63DU4pkezA3kGN81jGbwbrsMPpiOF" 72 }`, 73 }, 74 { 75 name: "get public key bytes RSA JWK", 76 jwkJSON: `{ 77 "kty": "RSA", 78 "e": "AQAB", 79 "use": "enc", 80 "kid": "sample@sample.id", 81 "alg": "RS256", 82 "n": "1hOl09BUnwY7jFBqoZKa4XDmIuc0YFb4y_5ThiHhLRW68aNG5Vo23n3ugND2GK3PsguZqJ_HrWCGVuVlKTmFg` + 83 `JWQD9ZnVcYqScgHpQRhxMBi86PIvXR01D_PWXZZjvTRakpvQxUT5bVBdWnaBHQoxDBt0YIVi5a7x-gXB1aDlts4RTMpfS9BPmEjX` + 84 `4lciozwS6Ow_wTO3C2YGa_Our0ptIxr-x_3sMbPCN8Fe_iaBDezeDAm39xCNjFa1E735ipXA4eUW_6SzFJ5-bM2UKba2WE6xUaEa5G1` + 85 `MDDHCG5LKKd6Mhy7SSAzPOR2FTKYj89ch2asCPlbjHTu8jS6Iy8" 86 }`, 87 }, 88 { 89 name: "get public key bytes EC P-256 JWK", 90 jwkJSON: `{ 91 "kty": "EC", 92 "use": "enc", 93 "crv": "P-256", 94 "kid": "sample@sample.id", 95 "x": "JR7nhI47w7bxrNkp7Xt1nbmozNn-RB2Q-PWi7KHT8J0", 96 "y": "iXmKtH0caOgB1vV0CQwinwK999qdDvrssKhdbiAz9OI", 97 "alg": "ES256" 98 }`, 99 }, 100 { 101 name: "get public key bytes EC P-384 JWK", 102 jwkJSON: `{ 103 "kty": "EC", 104 "use": "enc", 105 "crv": "P-384", 106 "kid": "sample@sample.id", 107 "x": "GGFw14WnABx5S__MLwjy7WPgmPzCNbygbJikSqwx1nQ7APAiIyLeiAeZnAFQSr8C", 108 "y": "Bjev4lkaRbd4Ery0vnO8Ox4QgIDGbuflmFq0HhL-QHIe3KhqxrqZqbQYGlDNudEv", 109 "alg": "ES384" 110 }`, 111 }, 112 { 113 name: "get public key bytes EC P-521 JWK", 114 jwkJSON: `{ 115 "kty": "EC", 116 "use": "enc", 117 "crv": "P-521", 118 "kid": "sample@sample.id", 119 "x": "AZi-AxJkB09qw8dBnNrz53xM-wER0Y5IYXSEWSTtzI5Sdv_5XijQn9z-vGz1pMdww-C75GdpAzp2ghejZJSxbAd6", 120 "y": "AZzRvW8NBytGNbF3dyNOMHB0DHCOzGp8oYBv_ZCyJbQUUnq-TYX7j8-PlKe9Ce5acxZzrcUKVtJ4I8JgI5x9oXIW", 121 "alg": "ES521" 122 }`, 123 }, 124 { 125 name: "get public key bytes EC SECP256K1 JWK", 126 jwkJSON: `{ 127 "kty": "EC", 128 "use": "enc", 129 "crv": "secp256k1", 130 "kid": "sample@sample.id", 131 "x": "YRrvJocKf39GpdTnd-zBFE0msGDqawR-Cmtc6yKoFsM", 132 "y": "kE-dMH9S3mxnTXo0JFEhraCU_tVYFDfpu9tpP1LfVKQ", 133 "alg": "ES256K" 134 }`, 135 }, 136 { 137 name: "get private key bytes EC SECP256K1 JWK", 138 jwkJSON: `{ 139 "kty": "EC", 140 "d": "Lg5xrN8Usd_T-MfqBIs3bUWQCNsXY8hGU-Ru3Joom8E", 141 "use": "sig", 142 "crv": "secp256k1", 143 "kid": "sample@sample.id", 144 "x": "dv6X5DheBaFWR2H_yv9pUI2dcmL2XX8m7zgFc9Coaqg", 145 "y": "AUVSmytVWP350kV1RHhQ6AcCWaJj8AFt4aNLlDws7C4", 146 "alg": "ES256K" 147 }`, 148 }, 149 } 150 151 t.Parallel() 152 153 for _, test := range tests { 154 tc := test 155 t.Run(tc.name, func(t *testing.T) { 156 var jwkKey jwk.JWK 157 158 err := json.Unmarshal([]byte(tc.jwkJSON), &jwkKey) 159 require.NoError(t, err) 160 161 pkBytes, err := jwkKey.PublicKeyBytes() 162 require.NoError(t, err) 163 require.NotEmpty(t, pkBytes) 164 165 jwkBytes, err := json.Marshal(&jwkKey) 166 require.NoError(t, err) 167 require.NotEmpty(t, jwkBytes) 168 169 switch tc.name { 170 case "get public key bytes X25519 JWK": 171 jwkKey1, err := JWKFromX25519Key(jwkKey.Key.([]byte)) 172 require.NoError(t, err) 173 require.NotNil(t, jwkKey1) 174 require.Equal(t, x25519Crv, jwkKey1.Crv) 175 require.Equal(t, cryptoutil.Curve25519KeySize, len(jwkKey1.Key.([]byte))) 176 require.Equal(t, okpKty, jwkKey1.Kty) 177 178 newJWK, err := PubKeyBytesToJWK(jwkKey.Key.([]byte), kms.X25519ECDHKWType) 179 require.NoError(t, err) 180 require.Equal(t, x25519Crv, newJWK.Crv) 181 require.Equal(t, cryptoutil.Curve25519KeySize, len(newJWK.Key.([]byte))) 182 require.Equal(t, okpKty, newJWK.Kty) 183 case "get public key bytes BBS+ JWK": 184 jwkKey2, err := JWKFromKey(jwkKey.Key) 185 require.NoError(t, err) 186 require.NotNil(t, jwkKey2) 187 require.Equal(t, bls12381G2Crv, jwkKey2.Crv) 188 bbsPubKey, ok := jwkKey2.Key.(*bbs12381g2pub.PublicKey) 189 require.True(t, ok) 190 bbsPubKeyBytes, err := bbsPubKey.Marshal() 191 require.NoError(t, err) 192 require.Equal(t, bls12381G2Size, len(bbsPubKeyBytes)) 193 require.Equal(t, ecKty, jwkKey2.Kty) 194 195 newJWK, err := PubKeyBytesToJWK(pkBytes, kms.BLS12381G2Type) 196 require.NoError(t, err) 197 require.NotNil(t, newJWK) 198 require.Equal(t, bls12381G2Crv, newJWK.Crv) 199 bbsPubKey, ok = newJWK.Key.(*bbs12381g2pub.PublicKey) 200 require.True(t, ok) 201 bbsPubKeyBytes, err = bbsPubKey.Marshal() 202 require.NoError(t, err) 203 require.Equal(t, bls12381G2Size, len(bbsPubKeyBytes)) 204 require.Equal(t, ecKty, newJWK.Kty) 205 case "get public key bytes Ed25519 JWK": 206 jwkKey3, err := JWKFromKey(jwkKey.Key) 207 require.NoError(t, err) 208 require.NotNil(t, jwkKey3) 209 require.Equal(t, "Ed25519", jwkKey3.Crv) 210 require.Equal(t, ed25519.PublicKeySize, len(jwkKey3.Key.(ed25519.PublicKey))) 211 require.Equal(t, okpKty, jwkKey3.Kty) 212 213 newJWK, err := PubKeyBytesToJWK(pkBytes, kms.ED25519Type) 214 require.NoError(t, err) 215 require.NotNil(t, newJWK) 216 require.Equal(t, "Ed25519", newJWK.Crv) 217 require.Equal(t, ed25519.PublicKeySize, len(newJWK.Key.(ed25519.PublicKey))) 218 require.Equal(t, okpKty, newJWK.Kty) 219 case "get public key bytes EC SECP256K1 JWK": 220 jwkKey8, err := JWKFromKey(jwkKey.Key) 221 require.NoError(t, err) 222 require.NotNil(t, jwkKey8) 223 require.Equal(t, btcec.S256().Params().Name, jwkKey8.Crv) 224 require.Equal(t, "EC", jwkKey8.Kty) 225 ecKey, ok := jwkKey8.Key.(*ecdsa.PublicKey) 226 require.True(t, ok) 227 require.Equal(t, "YRrvJocKf39GpdTnd-zBFE0msGDqawR-Cmtc6yKoFsM", 228 base64.RawURLEncoding.EncodeToString(ecKey.X.Bytes())) 229 require.Equal(t, "kE-dMH9S3mxnTXo0JFEhraCU_tVYFDfpu9tpP1LfVKQ", 230 base64.RawURLEncoding.EncodeToString(ecKey.Y.Bytes())) 231 232 newJWK, err := PubKeyBytesToJWK(pkBytes, kms.ECDSASecp256k1TypeIEEEP1363) 233 require.NoError(t, err) 234 require.NotNil(t, newJWK) 235 require.Equal(t, btcec.S256().Params().Name, newJWK.Crv) 236 require.Equal(t, "EC", newJWK.Kty) 237 ecKey, ok = newJWK.Key.(*ecdsa.PublicKey) 238 require.True(t, ok) 239 require.Equal(t, "YRrvJocKf39GpdTnd-zBFE0msGDqawR-Cmtc6yKoFsM", 240 base64.RawURLEncoding.EncodeToString(ecKey.X.Bytes())) 241 require.Equal(t, "kE-dMH9S3mxnTXo0JFEhraCU_tVYFDfpu9tpP1LfVKQ", 242 base64.RawURLEncoding.EncodeToString(ecKey.Y.Bytes())) 243 244 case "get public key bytes EC P-256 JWK": 245 jwkKey4, err := JWKFromKey(jwkKey.Key) 246 require.NoError(t, err) 247 require.NotNil(t, jwkKey4) 248 require.Equal(t, elliptic.P256().Params().Name, jwkKey4.Crv) 249 require.Equal(t, "EC", jwkKey4.Kty) 250 ecKey, ok := jwkKey4.Key.(*ecdsa.PublicKey) 251 require.True(t, ok) 252 require.Equal(t, "JR7nhI47w7bxrNkp7Xt1nbmozNn-RB2Q-PWi7KHT8J0", 253 base64.RawURLEncoding.EncodeToString(ecKey.X.Bytes())) 254 require.Equal(t, "iXmKtH0caOgB1vV0CQwinwK999qdDvrssKhdbiAz9OI", 255 base64.RawURLEncoding.EncodeToString(ecKey.Y.Bytes())) 256 257 newJWK, err := PubKeyBytesToJWK(pkBytes, kms.ECDSAP256TypeIEEEP1363) 258 require.NoError(t, err) 259 require.NotNil(t, newJWK) 260 require.Equal(t, elliptic.P256().Params().Name, newJWK.Crv) 261 require.Equal(t, "EC", newJWK.Kty) 262 ecKey, ok = newJWK.Key.(*ecdsa.PublicKey) 263 require.True(t, ok) 264 require.Equal(t, "JR7nhI47w7bxrNkp7Xt1nbmozNn-RB2Q-PWi7KHT8J0", 265 base64.RawURLEncoding.EncodeToString(ecKey.X.Bytes())) 266 require.Equal(t, "iXmKtH0caOgB1vV0CQwinwK999qdDvrssKhdbiAz9OI", 267 base64.RawURLEncoding.EncodeToString(ecKey.Y.Bytes())) 268 case "get public key bytes EC P-384 JWK": 269 jwkKey5, err := JWKFromKey(jwkKey.Key) 270 require.NoError(t, err) 271 require.NotNil(t, jwkKey5) 272 require.Equal(t, elliptic.P384().Params().Name, jwkKey5.Crv) 273 require.Equal(t, "EC", jwkKey5.Kty) 274 ecKey, ok := jwkKey5.Key.(*ecdsa.PublicKey) 275 require.True(t, ok) 276 require.Equal(t, "GGFw14WnABx5S__MLwjy7WPgmPzCNbygbJikSqwx1nQ7APAiIyLeiAeZnAFQSr8C", 277 base64.RawURLEncoding.EncodeToString(ecKey.X.Bytes())) 278 require.Equal(t, "Bjev4lkaRbd4Ery0vnO8Ox4QgIDGbuflmFq0HhL-QHIe3KhqxrqZqbQYGlDNudEv", 279 base64.RawURLEncoding.EncodeToString(ecKey.Y.Bytes())) 280 281 newJWK, err := PubKeyBytesToJWK(pkBytes, kms.ECDSAP384TypeIEEEP1363) 282 require.NoError(t, err) 283 require.NotNil(t, newJWK) 284 require.Equal(t, elliptic.P384().Params().Name, newJWK.Crv) 285 require.Equal(t, "EC", newJWK.Kty) 286 ecKey, ok = newJWK.Key.(*ecdsa.PublicKey) 287 require.True(t, ok) 288 require.Equal(t, "GGFw14WnABx5S__MLwjy7WPgmPzCNbygbJikSqwx1nQ7APAiIyLeiAeZnAFQSr8C", 289 base64.RawURLEncoding.EncodeToString(ecKey.X.Bytes())) 290 require.Equal(t, "Bjev4lkaRbd4Ery0vnO8Ox4QgIDGbuflmFq0HhL-QHIe3KhqxrqZqbQYGlDNudEv", 291 base64.RawURLEncoding.EncodeToString(ecKey.Y.Bytes())) 292 case "get public key bytes EC P-521 JWK": 293 jwkKey6, err := JWKFromKey(jwkKey.Key) 294 require.NoError(t, err) 295 require.NotNil(t, jwkKey6) 296 require.Equal(t, elliptic.P521().Params().Name, jwkKey6.Crv) 297 require.Equal(t, "EC", jwkKey6.Kty) 298 ecKey, ok := jwkKey6.Key.(*ecdsa.PublicKey) 299 require.True(t, ok) 300 require.Equal(t, "AZi-AxJkB09qw8dBnNrz53xM-wER0Y5IYXSEWSTtzI5Sdv_5XijQn9z-vGz1pMdww-C75GdpAzp2ghejZJSxbAd6", 301 base64.RawURLEncoding.EncodeToString(ecKey.X.Bytes())) 302 require.Equal(t, "AZzRvW8NBytGNbF3dyNOMHB0DHCOzGp8oYBv_ZCyJbQUUnq-TYX7j8-PlKe9Ce5acxZzrcUKVtJ4I8JgI5x9oXIW", 303 base64.RawURLEncoding.EncodeToString(ecKey.Y.Bytes())) 304 305 newJWK, err := PubKeyBytesToJWK(pkBytes, kms.ECDSAP521TypeIEEEP1363) 306 require.NoError(t, err) 307 require.NotNil(t, newJWK) 308 require.Equal(t, elliptic.P521().Params().Name, newJWK.Crv) 309 require.Equal(t, "EC", newJWK.Kty) 310 ecKey, ok = newJWK.Key.(*ecdsa.PublicKey) 311 require.True(t, ok) 312 require.Equal(t, "AZi-AxJkB09qw8dBnNrz53xM-wER0Y5IYXSEWSTtzI5Sdv_5XijQn9z-vGz1pMdww-C75GdpAzp2ghejZJSxbAd6", 313 base64.RawURLEncoding.EncodeToString(ecKey.X.Bytes())) 314 require.Equal(t, "AZzRvW8NBytGNbF3dyNOMHB0DHCOzGp8oYBv_ZCyJbQUUnq-TYX7j8-PlKe9Ce5acxZzrcUKVtJ4I8JgI5x9oXIW", 315 base64.RawURLEncoding.EncodeToString(ecKey.Y.Bytes())) 316 default: 317 jwkKey7, err := JWKFromKey(jwkKey.Key) 318 require.NoError(t, err) 319 require.NotNil(t, jwkKey7) 320 } 321 }) 322 } 323 }) 324 } 325 326 func TestJWKFromPublicKeyFailure(t *testing.T) { 327 key, err := JWKFromKey(nil) 328 require.Error(t, err) 329 require.Contains(t, err.Error(), "create JWK") 330 require.Nil(t, key) 331 } 332 333 func TestJWKFromX25519KeyFailure(t *testing.T) { 334 key, err := JWKFromX25519Key([]byte(strings.Repeat("a", 33))) // try to create a key larger than X25519 335 require.EqualError(t, err, "create JWK: marshalX25519: invalid key") 336 require.Nil(t, key) 337 338 key, err = JWKFromX25519Key(nil) // try to create a nil key 339 require.EqualError(t, err, "create JWK: marshalX25519: invalid key") 340 require.Nil(t, key) 341 } 342 343 func TestBBSJWK(t *testing.T) { 344 t.Run("test JWKFromKey() from BBS private key", func(t *testing.T) { 345 var jwk1 *jwk.JWK 346 347 _, privateKey, err := bbs12381g2pub.GenerateKeyPair(sha256.New, nil) 348 require.NoError(t, err) 349 350 jwkKey := &jwk.JWK{ 351 JSONWebKey: jose.JSONWebKey{ 352 Key: privateKey, 353 }, 354 Kty: ecKty, 355 Crv: bls12381G2Crv, 356 } 357 358 jwk1, err = JWKFromKey(privateKey) 359 require.NoError(t, err) 360 require.EqualValues(t, jwkKey, jwk1) 361 }) 362 } 363 364 func TestPubKeyBytesToKey(t *testing.T) { 365 tt := []struct { 366 keyTypes []kms.KeyType 367 getKey func(keyType kms.KeyType) ([]byte, error) 368 expectType interface{} 369 }{ 370 { 371 keyTypes: []kms.KeyType{kms.ED25519Type}, 372 getKey: func(kms.KeyType) ([]byte, error) { 373 pubKey, _, err := ed25519.GenerateKey(rand.Reader) 374 return pubKey, err 375 }, 376 expectType: ed25519.PublicKey{}, 377 }, 378 { 379 keyTypes: []kms.KeyType{kms.X25519ECDHKWType}, 380 getKey: func(kms.KeyType) ([]byte, error) { 381 pubKeyBytes := make([]byte, 32) 382 _, err := rand.Read(pubKeyBytes) 383 384 return pubKeyBytes, err 385 }, 386 expectType: []byte{}, 387 }, 388 { 389 keyTypes: []kms.KeyType{kms.BLS12381G2Type}, 390 getKey: func(kms.KeyType) ([]byte, error) { 391 pubKey, _, err := bbs12381g2pub.GenerateKeyPair(sha256.New, nil) 392 if err != nil { 393 return nil, err 394 } 395 396 keyBytes, err := pubKey.Marshal() 397 return keyBytes, err 398 }, 399 expectType: &bbs12381g2pub.PublicKey{}, 400 }, 401 { 402 keyTypes: []kms.KeyType{ 403 kms.ECDSAP256TypeIEEEP1363, 404 kms.ECDSAP384TypeIEEEP1363, 405 kms.ECDSAP521TypeIEEEP1363, 406 kms.ECDSASecp256k1TypeIEEEP1363, 407 }, 408 getKey: func(keyType kms.KeyType) ([]byte, error) { 409 crv := getECDSACurve(keyType) 410 privKey, err := ecdsa.GenerateKey(crv, rand.Reader) 411 if err != nil { 412 return nil, err 413 } 414 415 keyBytes := elliptic.Marshal(crv, privKey.X, privKey.Y) 416 return keyBytes, nil 417 }, 418 expectType: &ecdsa.PublicKey{}, 419 }, 420 { 421 keyTypes: []kms.KeyType{ 422 kms.ECDSAP256TypeDER, 423 kms.ECDSAP384TypeDER, 424 kms.ECDSAP521TypeDER, 425 }, 426 getKey: func(keyType kms.KeyType) ([]byte, error) { 427 crv := getECDSACurve(keyType) 428 privKey, err := ecdsa.GenerateKey(crv, rand.Reader) 429 if err != nil { 430 return nil, err 431 } 432 433 return x509.MarshalPKIXPublicKey(&privKey.PublicKey) 434 }, 435 expectType: &ecdsa.PublicKey{}, 436 }, 437 { 438 keyTypes: []kms.KeyType{ 439 kms.RSARS256, 440 kms.RSAPS256, 441 }, 442 getKey: func(keyType kms.KeyType) ([]byte, error) { 443 key, err := rsa.GenerateKey(rand.Reader, 2048) 444 if err != nil { 445 return nil, err 446 } 447 448 return x509.MarshalPKIXPublicKey(&key.PublicKey) 449 }, 450 expectType: &rsa.PublicKey{}, 451 }, 452 { 453 keyTypes: []kms.KeyType{ 454 kms.ECDSASecp256k1TypeDER, 455 }, 456 getKey: func(keyType kms.KeyType) ([]byte, error) { 457 priv, err := btcec.NewPrivateKey() 458 if err != nil { 459 return nil, err 460 } 461 462 pubKey := priv.PubKey() 463 464 return marshalSecp256k1DER(pubKey.ToECDSA()) 465 }, 466 expectType: &ecdsa.PublicKey{}, 467 }, 468 { 469 keyTypes: []kms.KeyType{ 470 kms.NISTP256ECDHKWType, 471 kms.NISTP384ECDHKWType, 472 kms.NISTP521ECDHKWType, 473 }, 474 getKey: func(keyType kms.KeyType) ([]byte, error) { 475 crv := getECDSACurve(keyType) 476 privKey, err := ecdsa.GenerateKey(crv, rand.Reader) 477 require.NoError(t, err) 478 479 pubKey := &cryptoapi.PublicKey{ 480 X: privKey.X.Bytes(), 481 Y: privKey.Y.Bytes(), 482 Curve: crv.Params().Name, 483 Type: "EC", 484 } 485 486 return json.Marshal(pubKey) 487 }, 488 expectType: &ecdsa.PublicKey{}, 489 }, 490 } 491 492 for _, tc := range tt { 493 for _, keyType := range tc.keyTypes { 494 t.Run(string(keyType), func(t *testing.T) { 495 pkBytes, err := tc.getKey(keyType) 496 require.NoError(t, err) 497 498 pk, err := PubKeyBytesToKey(pkBytes, keyType) 499 require.NoError(t, err) 500 501 require.IsType(t, tc.expectType, pk) 502 }) 503 } 504 } 505 506 t.Run("Secp256k1DER parse errors", func(t *testing.T) { 507 t.Run("asn.1 data invalid", func(t *testing.T) { 508 pkb := []byte("foo bar baz") 509 510 pk, err := PubKeyBytesToKey(pkb, kms.ECDSASecp256k1TypeDER) 511 require.Error(t, err) 512 require.Nil(t, pk) 513 }) 514 515 t.Run("data invalid", func(t *testing.T) { 516 pkb := []byte("foo bar baz") 517 518 pk, err := PubKeyBytesToKey(pkb, kms.ECDSASecp256k1TypeIEEEP1363) 519 require.Error(t, err) 520 require.Nil(t, pk) 521 }) 522 523 t.Run("asn.1 input has trailing data", func(t *testing.T) { 524 priv, err := btcec.NewPrivateKey() 525 require.NoError(t, err) 526 527 pubKey := priv.PubKey() 528 529 pkb, err := marshalSecp256k1DER(pubKey.ToECDSA()) 530 require.NoError(t, err) 531 532 pkb = append(pkb, 0, 0, 1, 1) 533 534 pk, err := PubKeyBytesToKey(pkb, kms.ECDSASecp256k1TypeDER) 535 require.Error(t, err) 536 require.Nil(t, pk) 537 }) 538 539 t.Run("not Secp256k1 key", func(t *testing.T) { 540 priv, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader) 541 require.NoError(t, err) 542 543 pubKey := priv.PublicKey 544 545 pkb, err := marshalSecp256k1DER(&pubKey) 546 require.NoError(t, err) 547 548 pkb = append(pkb, 0, 0, 1, 1) 549 550 pk, err := PubKeyBytesToKey(pkb, kms.ECDSASecp256k1TypeDER) 551 require.Error(t, err) 552 require.Nil(t, pk) 553 }) 554 }) 555 556 t.Run("invalid key type", func(t *testing.T) { 557 pkb := []byte("foo bar baz") 558 559 pk, err := PubKeyBytesToKey(pkb, "foo bar") 560 require.Error(t, err) 561 require.Contains(t, err.Error(), "invalid key type") 562 require.Nil(t, pk) 563 }) 564 } 565 566 func TestPubKeyBytesToJWK(t *testing.T) { 567 tests := []struct { 568 name string 569 keyType kms.KeyType 570 }{ 571 { 572 name: "P-256 IEEE1363 test", 573 keyType: kms.ECDSAP256TypeIEEEP1363, 574 }, 575 { 576 name: "P-384 IEEE1363 test", 577 keyType: kms.ECDSAP384TypeIEEEP1363, 578 }, 579 { 580 name: "P-521 IEEE1363 test", 581 keyType: kms.ECDSAP521TypeIEEEP1363, 582 }, 583 { 584 name: "P-256 DER test", 585 keyType: kms.ECDSAP256TypeDER, 586 }, 587 { 588 name: "P-384 DER test", 589 keyType: kms.ECDSAP384TypeDER, 590 }, 591 { 592 name: "P-521 DER test", 593 keyType: kms.ECDSAP521TypeDER, 594 }, 595 { 596 name: "Ed25519 test", 597 keyType: kms.ED25519Type, 598 }, 599 { 600 name: "BLS12381G2 test", 601 keyType: kms.BLS12381G2Type, 602 }, 603 { 604 name: "X25519 test", 605 keyType: kms.X25519ECDHKWType, 606 }, 607 { 608 name: "P-256 KW test", 609 keyType: kms.NISTP256ECDHKWType, 610 }, 611 { 612 name: "P-384 KW test", 613 keyType: kms.NISTP384ECDHKWType, 614 }, 615 { 616 name: "P-521 KW test", 617 keyType: kms.NISTP521ECDHKWType, 618 }, 619 { 620 name: "undefined type test", 621 keyType: "undefined", 622 }, 623 } 624 625 t.Parallel() 626 627 for _, test := range tests { 628 tc := test 629 t.Run(tc.name, func(t *testing.T) { 630 switch tc.keyType { 631 case kms.ED25519Type: 632 pubKey, _, err := ed25519.GenerateKey(rand.Reader) 633 require.NoError(t, err) 634 635 jwkKey, err := PubKeyBytesToJWK(pubKey, tc.keyType) 636 require.NoError(t, err) 637 require.NotEmpty(t, jwkKey) 638 require.Equal(t, okpKty, jwkKey.Kty) 639 require.Equal(t, "Ed25519", jwkKey.Crv) 640 case kms.BLS12381G2Type: 641 pubKey, _, err := bbs12381g2pub.GenerateKeyPair(sha256.New, nil) 642 require.NoError(t, err) 643 644 keyBytes, err := pubKey.Marshal() 645 require.NoError(t, err) 646 647 jwkKey, err := PubKeyBytesToJWK(keyBytes, tc.keyType) 648 require.NoError(t, err) 649 require.NotEmpty(t, jwkKey) 650 require.Equal(t, ecKty, jwkKey.Kty) 651 require.Equal(t, bls12381G2Crv, jwkKey.Crv) 652 653 _, err = PubKeyBytesToJWK([]byte("invalidbbsKey"), tc.keyType) 654 require.EqualError(t, err, "invalid size of public key") 655 case kms.ECDSAP256TypeIEEEP1363, kms.ECDSAP384TypeIEEEP1363, kms.ECDSAP521TypeIEEEP1363: 656 crv := getECDSACurve(tc.keyType) 657 privKey, err := ecdsa.GenerateKey(crv, rand.Reader) 658 require.NoError(t, err) 659 660 keyBytes := elliptic.Marshal(crv, privKey.X, privKey.Y) 661 662 jwkKey, err := PubKeyBytesToJWK(keyBytes, tc.keyType) 663 require.NoError(t, err) 664 require.NotEmpty(t, jwkKey) 665 require.Equal(t, "EC", jwkKey.Kty) 666 require.Equal(t, crv.Params().Name, jwkKey.Crv) 667 case kms.ECDSAP256TypeDER, kms.ECDSAP384TypeDER, kms.ECDSAP521TypeDER: 668 crv := getECDSACurve(tc.keyType) 669 privKey, err := ecdsa.GenerateKey(crv, rand.Reader) 670 require.NoError(t, err) 671 672 keyBytes, err := x509.MarshalPKIXPublicKey(&privKey.PublicKey) 673 require.NoError(t, err) 674 675 jwkKey, err := PubKeyBytesToJWK(keyBytes, tc.keyType) 676 require.NoError(t, err) 677 require.NotEmpty(t, jwkKey) 678 require.Equal(t, "EC", jwkKey.Kty) 679 require.Equal(t, crv.Params().Name, jwkKey.Crv) 680 681 _, err = PubKeyBytesToJWK([]byte("invalid EC Key"), tc.keyType) 682 require.Error(t, err) 683 require.Contains(t, err.Error(), "asn1: structure error: tags don't match") 684 685 pubEdKey, _, err := ed25519.GenerateKey(rand.Reader) 686 require.NoError(t, err) 687 688 pubEdKeyBytes, err := x509.MarshalPKIXPublicKey(pubEdKey) 689 require.NoError(t, err) 690 691 _, err = PubKeyBytesToJWK(pubEdKeyBytes, tc.keyType) 692 require.EqualError(t, err, "invalid EC key") 693 case kms.NISTP256ECDHKWType, kms.NISTP384ECDHKWType, kms.NISTP521ECDHKWType: 694 crv := getECDSACurve(tc.keyType) 695 privKey, err := ecdsa.GenerateKey(crv, rand.Reader) 696 require.NoError(t, err) 697 698 pubKey := &cryptoapi.PublicKey{ 699 X: privKey.X.Bytes(), 700 Y: privKey.Y.Bytes(), 701 Curve: crv.Params().Name, 702 Type: "EC", 703 } 704 705 keyBytes, err := json.Marshal(pubKey) 706 require.NoError(t, err) 707 708 jwkKey, err := PubKeyBytesToJWK(keyBytes, tc.keyType) 709 require.NoError(t, err) 710 require.NotEmpty(t, jwkKey) 711 require.Equal(t, "EC", jwkKey.Kty) 712 require.Equal(t, crv.Params().Name, jwkKey.Crv) 713 714 _, err = PubKeyBytesToJWK([]byte("invalid EC Key"), tc.keyType) 715 require.EqualError(t, err, "invalid character 'i' looking for beginning of value") 716 case kms.X25519ECDHKWType: 717 pubKeyBytes := make([]byte, 32) 718 _, err := rand.Read(pubKeyBytes) 719 require.NoError(t, err) 720 721 jwkKey, err := PubKeyBytesToJWK(pubKeyBytes, tc.keyType) 722 require.NoError(t, err) 723 require.NotEmpty(t, jwkKey) 724 require.Equal(t, okpKty, jwkKey.Kty) 725 require.Equal(t, x25519Crv, jwkKey.Crv) 726 default: 727 _, err := PubKeyBytesToJWK([]byte{}, tc.keyType) 728 require.EqualError(t, err, "convertPubKeyJWK: invalid key type: undefined") 729 } 730 }) 731 } 732 } 733 734 func TestEmptyCurve(t *testing.T) { 735 crv := getECDSACurve(kms.ChaCha20Poly1305) 736 require.Empty(t, crv) 737 } 738 739 func TestPublicKeyFromJWK(t *testing.T) { 740 prv256Key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) 741 require.NoError(t, err) 742 743 jwk256PrivKey, err := JWKFromKey(prv256Key) 744 require.NoError(t, err) 745 746 jwk256PubKey, err := JWKFromKey(&prv256Key.PublicKey) 747 require.NoError(t, err) 748 749 prv384Key, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader) 750 require.NoError(t, err) 751 752 jwk384PrivKey, err := JWKFromKey(prv384Key) 753 require.NoError(t, err) 754 755 jwk384PubKey, err := JWKFromKey(&prv384Key.PublicKey) 756 require.NoError(t, err) 757 758 prv521Key, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader) 759 require.NoError(t, err) 760 761 jwk521PrivKey, err := JWKFromKey(prv521Key) 762 require.NoError(t, err) 763 764 jwk521PubKey, err := JWKFromKey(&prv521Key.PublicKey) 765 require.NoError(t, err) 766 767 edPubKey, edPrivKey, err := ed25519.GenerateKey(rand.Reader) 768 require.NoError(t, err) 769 770 jwkEdPrivKey, err := JWKFromKey(edPrivKey) 771 require.NoError(t, err) 772 773 jwkEdPubKey, err := JWKFromKey(edPubKey) 774 require.NoError(t, err) 775 776 bbsPubKey, bbsPrivKey, err := bbs12381g2pub.GenerateKeyPair(sha256.New, nil) 777 require.NoError(t, err) 778 779 jwkBLSPrivKey, err := JWKFromKey(bbsPrivKey) 780 require.NoError(t, err) 781 782 jwkBLSPubKey, err := JWKFromKey(bbsPubKey) 783 require.NoError(t, err) 784 785 tests := []struct { 786 name string 787 jwkKey *jwk.JWK 788 }{ 789 { 790 name: "success p-256 key from JWK with private key", 791 jwkKey: jwk256PrivKey, 792 }, 793 { 794 name: "success p-256 key from JWK with public key", 795 jwkKey: jwk256PubKey, 796 }, 797 { 798 name: "success p-384 key from JWK with private key", 799 jwkKey: jwk384PrivKey, 800 }, 801 { 802 name: "success p-384 key from JWK with public key", 803 jwkKey: jwk384PubKey, 804 }, 805 { 806 name: "success p-521 key from JWK with private key", 807 jwkKey: jwk521PrivKey, 808 }, 809 { 810 name: "success p-521 key from JWK with public key", 811 jwkKey: jwk521PubKey, 812 }, 813 { 814 name: "success ed25519 key from JWK with private key", 815 jwkKey: jwkEdPrivKey, 816 }, 817 { 818 name: "success ed25519 key from JWK with public key", 819 jwkKey: jwkEdPubKey, 820 }, 821 { 822 name: "success BBS key from JWK with private key", 823 jwkKey: jwkBLSPrivKey, 824 }, 825 { 826 name: "success BBS key from JWK with public key", 827 jwkKey: jwkBLSPubKey, 828 }, 829 { 830 name: "fail invalid key type", 831 jwkKey: &jwk.JWK{ 832 JSONWebKey: jose.JSONWebKey{ 833 Key: "badKeytype", 834 }, 835 Kty: "", 836 Crv: "", 837 }, 838 }, 839 } 840 841 for _, tt := range tests { 842 tc := tt 843 844 t.Run(tc.name, func(t *testing.T) { 845 var pubKey *cryptoapi.PublicKey 846 847 pubKey, err = PublicKeyFromJWK(tc.jwkKey) 848 if strings.HasPrefix(tc.name, "success ") { 849 require.NoError(t, err) 850 require.Equal(t, tc.jwkKey.Crv, pubKey.Curve) 851 } else if strings.EqualFold(tc.name, "fail invalid key type") { 852 require.EqualError(t, err, fmt.Sprintf("publicKeyFromJWK: unsupported jwk key type %T", tc.jwkKey.Key)) 853 } 854 }) 855 } 856 857 t.Run("failure with empty jwk", func(t *testing.T) { 858 _, err = PublicKeyFromJWK(nil) 859 require.EqualError(t, err, "publicKeyFromJWK: jwk is empty") 860 }) 861 } 862 863 func TestRSAKeyFailParse(t *testing.T) { 864 resultJWK, err := PubKeyBytesToJWK([]byte{0x1}, kms.RSARS256) 865 require.ErrorContains(t, err, "rsa: invalid public key") 866 require.Nil(t, resultJWK) 867 } 868 869 func TestRSAKey(t *testing.T) { 870 key, err := rsa.GenerateKey(rand.Reader, 2048) 871 require.NoError(t, err) 872 873 pubBytes, err := x509.MarshalPKIXPublicKey(&key.PublicKey) 874 require.NoError(t, err) 875 876 resultJWK, err := PubKeyBytesToJWK(pubBytes, kms.RSARS256) 877 require.NoError(t, err) 878 879 pb, err := PublicKeyFromJWK(resultJWK) 880 require.NoError(t, err) 881 require.NotNil(t, pb) 882 require.NotNil(t, pb.N) 883 require.NotNil(t, pb.E) 884 require.Equal(t, "RSA", pb.Type) 885 } 886 887 type PublicKeyInfo struct { 888 Raw asn1.RawContent 889 Algorithm pkix.AlgorithmIdentifier 890 PublicKey asn1.BitString 891 } 892 893 func marshalSecp256k1DER(pub *ecdsa.PublicKey) ([]byte, error) { 894 publicKeyBytes := elliptic.Marshal(pub.Curve, pub.X, pub.Y) 895 896 pki := PublicKeyInfo{ 897 Algorithm: pkix.AlgorithmIdentifier{ 898 Algorithm: asn1.ObjectIdentifier{ 899 2, 0, // incorrect but syntactically valid data to allow asn.1 marshal to succeed 900 }, 901 }, 902 PublicKey: asn1.BitString{ 903 Bytes: publicKeyBytes, 904 BitLength: 8 * len(publicKeyBytes), 905 }, 906 } 907 908 out, err := asn1.Marshal(pki) 909 if err != nil { 910 return nil, err 911 } 912 913 return out, nil 914 }