github.com/trustbloc/kms-go@v1.1.2/crypto/tinkcrypto/key_wrapper.go (about) 1 /* 2 Copyright SecureKey Technologies Inc. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package tinkcrypto 8 9 import ( 10 "crypto/ecdsa" 11 "crypto/elliptic" 12 "encoding/base64" 13 "errors" 14 "fmt" 15 "math/big" 16 17 josecipher "github.com/go-jose/go-jose/v3/cipher" 18 hybrid "github.com/google/tink/go/hybrid/subtle" 19 "github.com/google/tink/go/keyset" 20 "golang.org/x/crypto/chacha20poly1305" 21 "golang.org/x/crypto/curve25519" 22 23 "github.com/trustbloc/kms-go/util/cryptoutil" 24 25 cryptoapi "github.com/trustbloc/kms-go/spi/crypto" 26 27 "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/aead/subtle" 28 "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/composite/keyio" 29 ecdhpb "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/proto/ecdh_aead_go_proto" 30 ) 31 32 const defKeySize = 32 33 34 // deriveKEKAndWrap is the entry point for Crypto.WrapKey(). 35 func (t *Crypto) deriveKEKAndWrap(cek, apu, apv, tag []byte, senderKH interface{}, recPubKey *cryptoapi.PublicKey, 36 epkPrv *cryptoapi.PrivateKey, useXC20PKW bool) (*cryptoapi.RecipientWrappedKey, error) { 37 var ( 38 kek []byte 39 epk *cryptoapi.PublicKey 40 wrappingAlg string 41 err error 42 ) 43 44 if senderKH != nil { // ecdh1pu 45 wrappingAlg, kek, epk, apu, err = t.derive1PUKEK(len(cek), apu, apv, tag, senderKH, recPubKey, epkPrv, 46 useXC20PKW) 47 if err != nil { 48 return nil, fmt.Errorf("deriveKEKAndWrap: error ECDH-1PU kek derivation: %w", err) 49 } 50 } else { // ecdhes 51 wrappingAlg, kek, epk, apu, err = t.deriveESKEK(apu, apv, recPubKey, useXC20PKW) 52 if err != nil { 53 return nil, fmt.Errorf("deriveKEKAndWrap: error ECDH-ES kek derivation: %w", err) 54 } 55 } 56 57 return t.wrapRaw(kek, cek, apu, apv, wrappingAlg, recPubKey.KID, epk, useXC20PKW) 58 } 59 60 func (t *Crypto) wrapRaw(kek, cek, apu, apv []byte, alg, kid string, epk *cryptoapi.PublicKey, 61 useXC20PKW bool) (*cryptoapi.RecipientWrappedKey, error) { 62 var wk []byte 63 64 if useXC20PKW { // nolint: nestif // XC20P key wrap 65 aead, err := t.okpKW.createPrimitive(kek) 66 if err != nil { 67 return nil, fmt.Errorf("deriveKEKAndWrap: failed to create new XC20P primitive: %w", err) 68 } 69 70 wk, err = t.okpKW.wrap(aead, cek) 71 if err != nil { 72 return nil, fmt.Errorf("deriveKEKAndWrap: failed to XC20P wrap key: %w", err) 73 } 74 } else { // A256GCM key wrap 75 block, err := t.ecKW.createPrimitive(kek) 76 if err != nil { 77 return nil, fmt.Errorf("deriveKEKAndWrap: failed to create new AES Cipher: %w", err) 78 } 79 80 wk, err = t.ecKW.wrap(block, cek) 81 if err != nil { 82 return nil, fmt.Errorf("deriveKEKAndWrap: failed to AES wrap key: %w", err) 83 } 84 } 85 86 return &cryptoapi.RecipientWrappedKey{ 87 KID: kid, 88 EncryptedCEK: wk, 89 EPK: *epk, 90 APU: apu, 91 APV: apv, 92 Alg: alg, 93 }, nil 94 } 95 96 // deriveKEKAndUnwrap is the entry point for Crypto.UnwrapKey(). 97 func (t *Crypto) deriveKEKAndUnwrap(alg string, encCEK, apu, apv, tag []byte, epk *cryptoapi.PublicKey, senderKH, 98 recKH interface{}) ([]byte, error) { 99 var ( 100 kek []byte 101 err error 102 ) 103 104 recPrivKH, ok := recKH.(*keyset.Handle) 105 if !ok { 106 return nil, fmt.Errorf("deriveKEKAndUnwrap: %w", errBadKeyHandleFormat) 107 } 108 109 recipientPrivateKey, err := extractPrivKey(recPrivKH) 110 if err != nil { 111 return nil, fmt.Errorf("deriveKEKAndUnwrap: %w", err) 112 } 113 114 switch alg { 115 case ECDH1PUA128KWAlg, ECDH1PUA192KWAlg, ECDH1PUA256KWAlg, ECDH1PUXC20PKWAlg: 116 kek, err = t.derive1PUKEKForUnwrap(alg, apu, apv, tag, epk, senderKH, recipientPrivateKey) 117 if err != nil { 118 return nil, fmt.Errorf("deriveKEKAndUnwrap: error ECDH-1PU kek derivation: %w", err) 119 } 120 case ECDHESA256KWAlg, ECDHESXC20PKWAlg: 121 kek, err = t.deriveESKEKForUnwrap(alg, apu, apv, epk, recipientPrivateKey) 122 if err != nil { 123 return nil, fmt.Errorf("deriveKEKAndUnwrap: error ECDH-ES kek derivation: %w", err) 124 } 125 default: 126 return nil, fmt.Errorf("deriveKEKAndUnwrap: unsupported JWE KW Alg '%s'", alg) 127 } 128 129 return t.unwrapRaw(alg, kek, encCEK) 130 } 131 132 func (t *Crypto) unwrapRaw(alg string, kek, encCEK []byte) ([]byte, error) { 133 var wk []byte 134 135 // key unwrapping does not depend on an option (like key wrapping), because kw primitive can be detected from alg. 136 switch alg { 137 case ECDHESXC20PKWAlg, ECDH1PUXC20PKWAlg: // XC20P key unwrap 138 aead, err := t.okpKW.createPrimitive(kek) 139 if err != nil { 140 return nil, fmt.Errorf("deriveKEKAndUnwrap: failed to create new XC20P primitive: %w", err) 141 } 142 143 wk, err = t.okpKW.unwrap(aead, encCEK) 144 if err != nil { 145 return nil, fmt.Errorf("deriveKEKAndUnwrap: failed to XC20P unwrap key: %w", err) 146 } 147 case ECDHESA256KWAlg, ECDH1PUA128KWAlg, ECDH1PUA192KWAlg, ECDH1PUA256KWAlg: 148 // A256GCM key (ES) unwrap or CBC+HMAC (1PU) 149 block, err := t.ecKW.createPrimitive(kek) 150 if err != nil { 151 return nil, fmt.Errorf("deriveKEKAndUnwrap: failed to create new AES Cipher: %w", err) 152 } 153 154 wk, err = t.ecKW.unwrap(block, encCEK) 155 if err != nil { 156 return nil, fmt.Errorf("deriveKEKAndUnwrap: failed to AES unwrap key: %w", err) 157 } 158 default: 159 return nil, fmt.Errorf("deriveKEKAndUnwrap: cannot unwrap with bad kw alg: '%s'", alg) 160 } 161 162 return wk, nil 163 } 164 165 func (t *Crypto) derive1PUKEK(cekSize int, apu, apv, tag []byte, senderKH interface{}, recPubKey *cryptoapi.PublicKey, 166 epkPrv *cryptoapi.PrivateKey, useXC20PKW bool) (string, []byte, *cryptoapi.PublicKey, []byte, error) { 167 var ( 168 kek []byte 169 epk *cryptoapi.PublicKey 170 err error 171 wrappingAlg string 172 ) 173 174 two := 2 175 176 if useXC20PKW { 177 wrappingAlg = ECDH1PUXC20PKWAlg 178 } else { 179 switch cekSize { 180 case subtle.AES128Size * two: 181 wrappingAlg = ECDH1PUA128KWAlg 182 case subtle.AES192Size * two: 183 wrappingAlg = ECDH1PUA192KWAlg 184 case subtle.AES256Size * two: 185 wrappingAlg = ECDH1PUA256KWAlg 186 default: 187 return "", nil, nil, nil, fmt.Errorf("derive1PUKEK: invalid CBC-HMAC key size %d", cekSize) 188 } 189 } 190 191 switch recPubKey.Type { 192 case ecdhpb.KeyType_EC.String(): 193 wrappingAlg, kek, epk, apu, err = t.derive1PUWithECKey(wrappingAlg, apu, apv, tag, senderKH, recPubKey, epkPrv) 194 if err != nil { 195 return "", nil, nil, nil, fmt.Errorf("derive1PUKEK: EC key derivation error %w", err) 196 } 197 case ecdhpb.KeyType_OKP.String(): 198 wrappingAlg, kek, epk, apu, err = t.derive1PUWithOKPKey(wrappingAlg, apu, apv, tag, senderKH, recPubKey, epkPrv) 199 if err != nil { 200 return "", nil, nil, nil, fmt.Errorf("derive1PUKEK: OKP key derivation error %w", err) 201 } 202 default: 203 return "", nil, nil, nil, errors.New("derive1PUKEK: invalid recipient key type for ECDH-1PU") 204 } 205 206 return wrappingAlg, kek, epk, apu, nil 207 } 208 209 func (t *Crypto) derive1PUKEKForUnwrap(alg string, apu, apv, tag []byte, epk *cryptoapi.PublicKey, senderKH interface{}, 210 recipientPrivateKey interface{}) ([]byte, error) { 211 var ( 212 kek []byte 213 err error 214 ) 215 216 if senderKH == nil { 217 return nil, fmt.Errorf("derive1PUKEKForUnwrap: sender's public keyset handle option is required for '%s'", 218 ECDH1PUA256KWAlg) 219 } 220 221 switch epk.Type { 222 case ecdhpb.KeyType_EC.String(): 223 kek, err = t.derive1PUWithECKeyForUnwrap(alg, apu, apv, tag, epk, senderKH, recipientPrivateKey) 224 if err != nil { 225 return nil, fmt.Errorf("derive1PUKEKForUnwrap: EC key derivation error %w", err) 226 } 227 case ecdhpb.KeyType_OKP.String(): 228 kek, err = t.derive1PUWithOKPKeyForUnwrap(alg, apu, apv, tag, epk, senderKH, recipientPrivateKey) 229 if err != nil { 230 return nil, fmt.Errorf("derive1PUKEKForUnwrap: OKP key derivation error %w", err) 231 } 232 default: 233 return nil, errors.New("derive1PUKEKForUnwrap: invalid EPK key type for ECDH-1PU") 234 } 235 236 return kek, nil 237 } 238 239 func (t *Crypto) deriveESKEK(apu, apv []byte, recPubKey *cryptoapi.PublicKey, 240 useXC20PKW bool) (string, []byte, *cryptoapi.PublicKey, []byte, error) { 241 var ( 242 kek []byte 243 epk *cryptoapi.PublicKey 244 wrappingAlg string 245 err error 246 ) 247 248 switch recPubKey.Type { 249 case ecdhpb.KeyType_EC.String(): 250 wrappingAlg, kek, epk, apu, err = t.deriveESWithECKey(apu, apv, recPubKey, useXC20PKW) 251 if err != nil { 252 return "", nil, nil, nil, fmt.Errorf("deriveESKEK: error %w", err) 253 } 254 case ecdhpb.KeyType_OKP.String(): 255 wrappingAlg, kek, epk, apu, err = t.deriveESWithOKPKey(apu, apv, recPubKey, useXC20PKW) 256 if err != nil { 257 return "", nil, nil, nil, fmt.Errorf("deriveESKEK: error %w", err) 258 } 259 default: 260 return "", nil, nil, nil, errors.New("deriveESKEK: invalid recipient key type for ECDH-ES") 261 } 262 263 return wrappingAlg, kek, epk, apu, nil 264 } 265 266 func (t *Crypto) deriveESKEKForUnwrap(alg string, apu, apv []byte, epk *cryptoapi.PublicKey, 267 recipientPrivateKey interface{}) ([]byte, error) { 268 var ( 269 kek []byte 270 err error 271 ) 272 273 switch epk.Type { 274 case ecdhpb.KeyType_EC.String(): 275 kek, err = t.deriveESWithECKeyForUnwrap(alg, apu, apv, epk, recipientPrivateKey) 276 if err != nil { 277 return nil, fmt.Errorf("deriveESKEKForUnwrap: error: %w", err) 278 } 279 case ecdhpb.KeyType_OKP.String(): 280 kek, err = t.deriveESWithOKPKeyForUnwrap(alg, apu, apv, epk, recipientPrivateKey) 281 if err != nil { 282 return nil, fmt.Errorf("deriveESKEKForUnwrap: error: %w", err) 283 } 284 default: 285 return nil, errors.New("deriveESKEKForUnwrap: invalid EPK key type for ECDH-ES") 286 } 287 288 return kek, nil 289 } 290 291 func (t *Crypto) derive1PUWithECKey(wrappingAlg string, apu, apv, tag []byte, senderKH interface{}, 292 recPubKey *cryptoapi.PublicKey, epkPrv *cryptoapi.PrivateKey) (string, []byte, *cryptoapi.PublicKey, []byte, error) { 293 senderPrivKey, err := ksToPrivateECDSAKey(senderKH) 294 if err != nil { 295 return "", nil, nil, nil, fmt.Errorf("derive1PUWithECKey: failed to retrieve sender key: %w", err) 296 } 297 298 pubKey, ephemeralPrivKey, err := t.convertRecKeyAndGenOrGetEPKEC(recPubKey, epkPrv) 299 if err != nil { 300 return "", nil, nil, nil, err 301 } 302 303 ephemeralXBytes := ephemeralPrivKey.PublicKey.X.Bytes() 304 305 if len(apu) == 0 { 306 apu = make([]byte, base64.RawURLEncoding.EncodedLen(len(ephemeralXBytes))) 307 base64.RawURLEncoding.Encode(apu, ephemeralXBytes) 308 } 309 310 keySize := aesCEKSize1PU(wrappingAlg) 311 312 kek, err := t.ecKW.deriveSender1Pu(wrappingAlg, apu, apv, tag, ephemeralPrivKey, senderPrivKey, pubKey, keySize) 313 if err != nil { 314 return "", nil, nil, nil, fmt.Errorf("derive1PUWithECKey: failed to derive key: %w", err) 315 } 316 317 epk := &cryptoapi.PublicKey{ 318 X: ephemeralXBytes, 319 Y: ephemeralPrivKey.PublicKey.Y.Bytes(), 320 Curve: ephemeralPrivKey.PublicKey.Curve.Params().Name, 321 Type: recPubKey.Type, 322 } 323 324 return wrappingAlg, kek, epk, apu, nil 325 } 326 327 func (t *Crypto) derive1PUWithECKeyForUnwrap(alg string, apu, apv, tag []byte, epk *cryptoapi.PublicKey, 328 senderKH interface{}, recipientPrivateKey interface{}) ([]byte, error) { 329 var ( 330 senderPubKey *ecdsa.PublicKey 331 epkCurve elliptic.Curve 332 err error 333 ) 334 335 senderPubKey, err = ksToPublicECDSAKey(senderKH, t.ecKW) 336 if err != nil { 337 return nil, fmt.Errorf("derive1PUWithECKeyForUnwrap: failed to retrieve sender key: %w", err) 338 } 339 340 epkCurve, err = t.ecKW.getCurve(epk.Curve) 341 if err != nil { 342 return nil, fmt.Errorf("derive1PUWithECKeyForUnwrap: failed to GetCurve: %w", err) 343 } 344 345 epkPubKey := &ecdsa.PublicKey{ 346 Curve: epkCurve, 347 X: new(big.Int).SetBytes(epk.X), 348 Y: new(big.Int).SetBytes(epk.Y), 349 } 350 351 recPrivECKey, ok := recipientPrivateKey.(*hybrid.ECPrivateKey) 352 if !ok { 353 return nil, errors.New("derive1PUWithECKeyForUnwrap: recipient key is not an EC key") 354 } 355 356 recPrivKey := hybridECPrivToECDSAKey(recPrivECKey) 357 358 keySize := aesCEKSize1PU(alg) 359 360 kek, err := t.ecKW.deriveRecipient1Pu(alg, apu, apv, tag, epkPubKey, senderPubKey, recPrivKey, keySize) 361 if err != nil { 362 return nil, fmt.Errorf("derive1PUWithECKeyForUnwrap: failed to derive kek: %w", err) 363 } 364 365 return kek, nil 366 } 367 368 func aesCEKSize1PU(alg string) int { 369 keySize := defKeySize 370 two := 2 371 372 switch alg { 373 case ECDH1PUA128KWAlg: 374 keySize = subtle.AES128Size * two 375 case ECDH1PUA192KWAlg: 376 keySize = subtle.AES192Size * two 377 case ECDH1PUA256KWAlg: 378 keySize = subtle.AES256Size * two 379 } 380 381 return keySize 382 } 383 384 func (t *Crypto) deriveESWithECKeyForUnwrap(alg string, apu, apv []byte, epk *cryptoapi.PublicKey, 385 recipientPrivateKey interface{}) ([]byte, error) { 386 var ( 387 epkCurve elliptic.Curve 388 err error 389 ) 390 391 epkCurve, err = t.ecKW.getCurve(epk.Curve) 392 if err != nil { 393 return nil, fmt.Errorf("deriveESWithECKeyForUnwrap: failed to GetCurve: %w", err) 394 } 395 396 epkPubKey := &ecdsa.PublicKey{ 397 Curve: epkCurve, 398 X: new(big.Int).SetBytes(epk.X), 399 Y: new(big.Int).SetBytes(epk.Y), 400 } 401 402 recPrivECKey, ok := recipientPrivateKey.(*hybrid.ECPrivateKey) 403 if !ok { 404 return nil, errors.New("deriveESWithECKeyForUnwrap: recipient key is not an EC key") 405 } 406 407 recPrivKey := hybridECPrivToECDSAKey(recPrivECKey) 408 409 if recPrivKey.Curve != epkPubKey.Curve { 410 return nil, errors.New("deriveESWithECKeyForUnwrap: recipient and ephemeral keys are not on the same curve") 411 } 412 413 return josecipher.DeriveECDHES(alg, apu, apv, recPrivKey, epkPubKey, defKeySize), nil 414 } 415 416 func (t *Crypto) deriveESWithECKey(apu, apv []byte, recPubKey *cryptoapi.PublicKey, 417 useXC20PKW bool) (string, []byte, *cryptoapi.PublicKey, []byte, error) { 418 wrappingAlg := ECDHESA256KWAlg 419 420 if useXC20PKW { 421 wrappingAlg = ECDHESXC20PKWAlg 422 } 423 424 recECPubKey, ephemeralPrivKey, err := t.convertRecKeyAndGenOrGetEPKEC(recPubKey, nil) 425 if err != nil { 426 return "", nil, nil, nil, fmt.Errorf("deriveESWithECKey: failed to generate ephemeral key: %w", err) 427 } 428 429 ephemeralXBytes := ephemeralPrivKey.PublicKey.X.Bytes() 430 431 if len(apu) == 0 { 432 apu = make([]byte, base64.RawURLEncoding.EncodedLen(len(ephemeralXBytes))) 433 base64.RawURLEncoding.Encode(apu, ephemeralXBytes) 434 } 435 436 kek := josecipher.DeriveECDHES(wrappingAlg, apu, apv, ephemeralPrivKey, recECPubKey, defKeySize) 437 epk := &cryptoapi.PublicKey{ 438 X: ephemeralXBytes, 439 Y: ephemeralPrivKey.PublicKey.Y.Bytes(), 440 Curve: ephemeralPrivKey.PublicKey.Curve.Params().Name, 441 Type: recPubKey.Type, 442 } 443 444 return wrappingAlg, kek, epk, apu, nil 445 } 446 447 func (t *Crypto) derive1PUWithOKPKey(wrappingAlg string, apu, apv, tag []byte, senderKH interface{}, 448 recPubKey *cryptoapi.PublicKey, epkPrv *cryptoapi.PrivateKey) (string, []byte, *cryptoapi.PublicKey, []byte, error) { 449 senderPrivKey, err := ksToPrivateX25519Key(senderKH) 450 if err != nil { 451 return "", nil, nil, nil, fmt.Errorf("derive1PUWithOKPKey: failed to retrieve sender key: %w", err) 452 } 453 454 ephemeralPubKey, ephemeralPrivKey, err := t.generateOrGetEphemeralOKPKey(epkPrv) 455 if err != nil { 456 return "", nil, nil, nil, fmt.Errorf("derive1PUWithOKPKey: failed to generate ephemeral key: %w", err) 457 } 458 459 if len(apu) == 0 { 460 apu = make([]byte, base64.RawURLEncoding.EncodedLen(len(ephemeralPubKey))) 461 base64.RawURLEncoding.Encode(apu, ephemeralPubKey) 462 } 463 464 kek, err := t.okpKW.deriveSender1Pu(wrappingAlg, apu, apv, tag, ephemeralPrivKey, senderPrivKey, recPubKey.X, 465 defKeySize) 466 if err != nil { 467 return "", nil, nil, nil, fmt.Errorf("derive1PUWithOKPKey: failed to derive key: %w", err) 468 } 469 470 epk := &cryptoapi.PublicKey{ 471 X: ephemeralPubKey, 472 Curve: "X25519", 473 Type: recPubKey.Type, 474 } 475 476 return wrappingAlg, kek, epk, apu, nil 477 } 478 479 func (t *Crypto) derive1PUWithOKPKeyForUnwrap(alg string, apu, apv, tag []byte, epk *cryptoapi.PublicKey, 480 senderKH interface{}, recipientPrivateKey interface{}) ([]byte, error) { 481 senderPubKey, err := ksToPublicX25519Key(senderKH) 482 if err != nil { 483 return nil, fmt.Errorf("derive1PUWithOKPKeyForUnwrap: failed to retrieve sender key: %w", err) 484 } 485 486 recPrivOKPKey, ok := recipientPrivateKey.([]byte) 487 if !ok { 488 return nil, errors.New("derive1PUWithOKPKeyForUnwrap: recipient key is not an OKP key") 489 } 490 491 kek, err := t.okpKW.deriveRecipient1Pu(alg, apu, apv, tag, epk.X, senderPubKey, recPrivOKPKey, defKeySize) 492 if err != nil { 493 return nil, fmt.Errorf("derive1PUWithOKPKeyForUnwrap: failed to derive kek: %w", err) 494 } 495 496 return kek, nil 497 } 498 499 func (t *Crypto) deriveESWithOKPKey(apu, apv []byte, recPubKey *cryptoapi.PublicKey, 500 useXC20PKW bool) (string, []byte, *cryptoapi.PublicKey, []byte, error) { 501 wrappingAlg := ECDHESA256KWAlg 502 503 if useXC20PKW { 504 wrappingAlg = ECDHESXC20PKWAlg 505 } 506 507 ephemeralPubKey, ephemeralPrivKey, err := t.generateOrGetEphemeralOKPKey(nil) 508 if err != nil { 509 return "", nil, nil, nil, fmt.Errorf("deriveESWithOKPKey: failed to generate ephemeral key: %w", err) 510 } 511 512 ephemeralPrivChacha := new([chacha20poly1305.KeySize]byte) 513 copy(ephemeralPrivChacha[:], ephemeralPrivKey) 514 515 recPubKeyChacha := new([chacha20poly1305.KeySize]byte) 516 copy(recPubKeyChacha[:], recPubKey.X) 517 518 if len(apu) == 0 { 519 apu = make([]byte, base64.RawURLEncoding.EncodedLen(len(ephemeralPubKey))) 520 base64.RawURLEncoding.Encode(apu, ephemeralPubKey) 521 } 522 523 z, err := cryptoutil.DeriveECDHX25519(ephemeralPrivChacha, recPubKeyChacha) 524 if err != nil { 525 return "", nil, nil, nil, fmt.Errorf("deriveESWithOKPKey: failed to derive 25519 kek: %w", err) 526 } 527 528 kek := kdf(wrappingAlg, z, apu, apv, chacha20poly1305.KeySize) 529 530 epk := &cryptoapi.PublicKey{ 531 X: ephemeralPubKey, 532 Curve: "X25519", 533 Type: recPubKey.Type, 534 } 535 536 return wrappingAlg, kek, epk, apu, nil 537 } 538 539 func (t *Crypto) deriveESWithOKPKeyForUnwrap(alg string, apu, apv []byte, epk *cryptoapi.PublicKey, 540 recipientPrivateKey interface{}) ([]byte, error) { 541 recPrivOKPKey, ok := recipientPrivateKey.([]byte) 542 if !ok { 543 return nil, errors.New("deriveESWithOKPKeyForUnwrap: recipient key is not an OKP key") 544 } 545 546 recPrivKeyChacha := new([chacha20poly1305.KeySize]byte) 547 copy(recPrivKeyChacha[:], recPrivOKPKey) 548 549 epkChacha := new([chacha20poly1305.KeySize]byte) 550 copy(epkChacha[:], epk.X) 551 552 z, err := cryptoutil.DeriveECDHX25519(recPrivKeyChacha, epkChacha) 553 if err != nil { 554 return nil, fmt.Errorf("deriveESWithOKPKeyForUnwrap: %w", err) 555 } 556 557 return kdf(alg, z, apu, apv, chacha20poly1305.KeySize), nil 558 } 559 560 // convertRecKeyAndGenOrGetEPKEC converts recPubKey into *ecdsa.PublicKey and generates an ephemeral EC private key 561 // as *ecdsa.PrivateKey. 562 func (t *Crypto) convertRecKeyAndGenOrGetEPKEC(recPubKey *cryptoapi.PublicKey, 563 prvEPK *cryptoapi.PrivateKey) (*ecdsa.PublicKey, *ecdsa.PrivateKey, 564 error) { 565 c, err := t.ecKW.getCurve(recPubKey.Curve) 566 if err != nil { 567 return nil, nil, fmt.Errorf("convertRecKeyAndGenOrGetEPKEC: failed to get curve of recipient key: %w", 568 err) 569 } 570 571 recECPubKey := &ecdsa.PublicKey{ 572 Curve: c, 573 X: new(big.Int).SetBytes(recPubKey.X), 574 Y: new(big.Int).SetBytes(recPubKey.Y), 575 } 576 577 if prvEPK == nil { 578 ephemeralPrivKey, err := t.ecKW.generateKey(recECPubKey.Curve) 579 if err != nil { 580 return nil, nil, fmt.Errorf("convertRecKeyAndGenOrGetEPKEC: failed to generate EPK: %w", err) 581 } 582 583 return recECPubKey, ephemeralPrivKey.(*ecdsa.PrivateKey), nil 584 } 585 586 return recECPubKey, &ecdsa.PrivateKey{ 587 PublicKey: ecdsa.PublicKey{ 588 Curve: c, 589 X: new(big.Int).SetBytes(prvEPK.PublicKey.X), 590 Y: new(big.Int).SetBytes(prvEPK.PublicKey.Y), 591 }, 592 D: new(big.Int).SetBytes(prvEPK.D), 593 }, nil 594 } 595 596 func (t *Crypto) generateOrGetEphemeralOKPKey(epkPrv *cryptoapi.PrivateKey) ([]byte, []byte, error) { 597 if epkPrv == nil { 598 ephemeralPrivKey, err := t.okpKW.generateKey(nil) 599 if err != nil { 600 return nil, nil, err 601 } 602 603 ephemeralPrivKeyByte, ok := ephemeralPrivKey.([]byte) 604 if !ok { 605 return nil, nil, errors.New("invalid ephemeral key type, not OKP, want []byte for OKP") 606 } 607 608 ephemeralPubKey, err := curve25519.X25519(ephemeralPrivKeyByte, curve25519.Basepoint) 609 if err != nil { 610 return nil, nil, err 611 } 612 613 return ephemeralPubKey, ephemeralPrivKeyByte, nil 614 } 615 616 return epkPrv.PublicKey.X, epkPrv.D, nil 617 } 618 619 func ksToPrivateECDSAKey(ks interface{}) (*ecdsa.PrivateKey, error) { 620 senderKH, ok := ks.(*keyset.Handle) 621 if !ok { 622 return nil, fmt.Errorf("ksToPrivateECDSAKey: %w", errBadKeyHandleFormat) 623 } 624 625 senderHPrivKey, err := extractPrivKey(senderKH) 626 if err != nil { 627 return nil, fmt.Errorf("ksToPrivateECDSAKey: failed to extract sender key: %w", err) 628 } 629 630 prvKey, ok := senderHPrivKey.(*hybrid.ECPrivateKey) 631 if !ok { 632 return nil, errors.New("ksToPrivateECDSAKey: not an EC key") 633 } 634 635 return hybridECPrivToECDSAKey(prvKey), nil 636 } 637 638 func ksToPrivateX25519Key(ks interface{}) ([]byte, error) { 639 senderKH, ok := ks.(*keyset.Handle) 640 if !ok { 641 return nil, fmt.Errorf("ksToPrivateX25519Key: %w", errBadKeyHandleFormat) 642 } 643 644 senderPrivKey, err := extractPrivKey(senderKH) 645 if err != nil { 646 return nil, fmt.Errorf("ksToPrivateX25519Key: failed to extract sender key: %w", err) 647 } 648 649 prvKey, ok := senderPrivKey.([]byte) 650 if !ok { 651 return nil, errors.New("ksToPrivateX25519Key: not an OKP key") 652 } 653 654 return prvKey, nil 655 } 656 657 func ksToPublicECDSAKey(ks interface{}, kw keyWrapper) (*ecdsa.PublicKey, error) { 658 switch kst := ks.(type) { 659 case *keyset.Handle: 660 sPubKey, err := keyio.ExtractPrimaryPublicKey(kst) 661 if err != nil { 662 return nil, fmt.Errorf("ksToPublicECDSAKey: failed to extract public key from keyset handle: %w", err) 663 } 664 665 sCurve, err := kw.getCurve(sPubKey.Curve) 666 if err != nil { 667 return nil, fmt.Errorf("ksToPublicECDSAKey: failed to GetCurve: %w", err) 668 } 669 670 return &ecdsa.PublicKey{ 671 Curve: sCurve, 672 X: new(big.Int).SetBytes(sPubKey.X), 673 Y: new(big.Int).SetBytes(sPubKey.Y), 674 }, nil 675 case *cryptoapi.PublicKey: 676 sCurve, err := kw.getCurve(kst.Curve) 677 if err != nil { 678 return nil, fmt.Errorf("ksToPublicECDSAKey: failed to GetCurve: %w", err) 679 } 680 681 return &ecdsa.PublicKey{ 682 Curve: sCurve, 683 X: new(big.Int).SetBytes(kst.X), 684 Y: new(big.Int).SetBytes(kst.Y), 685 }, nil 686 case *ecdsa.PublicKey: 687 return kst, nil 688 default: 689 return nil, fmt.Errorf("ksToPublicECDSAKey: unsupported keyset type %+v", kst) 690 } 691 } 692 693 func ksToPublicX25519Key(ks interface{}) ([]byte, error) { 694 switch kst := ks.(type) { 695 case *keyset.Handle: 696 sPubKey, err := keyio.ExtractPrimaryPublicKey(kst) 697 if err != nil { 698 return nil, fmt.Errorf("ksToPublicX25519Key: failed to extract public key from keyset handle: %w", err) 699 } 700 701 return sPubKey.X, nil 702 case *cryptoapi.PublicKey: 703 return kst.X, nil 704 default: 705 return nil, fmt.Errorf("ksToPublicX25519Key: unsupported keyset type %+v", kst) 706 } 707 }