github.com/trustbloc/kms-go@v1.1.2/crypto/tinkcrypto/unwrap_support.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 "bytes" 11 "crypto/ecdsa" 12 "crypto/elliptic" 13 "errors" 14 "fmt" 15 "io" 16 17 "github.com/golang/protobuf/proto" 18 hybrid "github.com/google/tink/go/hybrid/subtle" 19 "github.com/google/tink/go/keyset" 20 commonpb "github.com/google/tink/go/proto/common_go_proto" 21 tinkpb "github.com/google/tink/go/proto/tink_go_proto" 22 23 ecdhpb "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/proto/ecdh_aead_go_proto" 24 ) 25 26 func extractPrivKey(kh *keyset.Handle) (interface{}, error) { 27 buf := new(bytes.Buffer) 28 w := &privKeyWriter{w: buf} 29 nAEAD := &noopAEAD{} 30 31 if kh == nil { 32 return nil, fmt.Errorf("extractPrivKey: kh is nil") 33 } 34 35 err := kh.Write(w, nAEAD) 36 if err != nil { 37 return nil, fmt.Errorf("extractPrivKey: retrieving private key failed: %w", err) 38 } 39 40 ks := new(tinkpb.Keyset) 41 42 err = proto.Unmarshal(buf.Bytes(), ks) 43 if err != nil { 44 return nil, errors.New("extractPrivKey: invalid private key") 45 } 46 47 primaryKey := ks.Key[0] 48 49 switch primaryKey.KeyData.TypeUrl { 50 case nistPECDHKWPrivateKeyTypeURL: 51 pbKey := new(ecdhpb.EcdhAeadPrivateKey) 52 53 err = proto.Unmarshal(primaryKey.KeyData.Value, pbKey) 54 if err != nil { 55 return nil, errors.New("extractPrivKey: invalid key in keyset") 56 } 57 58 var c elliptic.Curve 59 60 c, err = hybrid.GetCurve(pbKey.PublicKey.Params.KwParams.CurveType.String()) 61 if err != nil { 62 return nil, fmt.Errorf("extractPrivKey: invalid key: %w", err) 63 } 64 65 return hybrid.GetECPrivateKey(c, pbKey.KeyValue), nil 66 case x25519ECDHKWPrivateKeyTypeURL: 67 pbKey := new(ecdhpb.EcdhAeadPrivateKey) 68 69 err = proto.Unmarshal(primaryKey.KeyData.Value, pbKey) 70 if err != nil { 71 return nil, errors.New("extractPrivKey: invalid key in keyset") 72 } 73 74 if pbKey.PublicKey.Params.KwParams.CurveType.String() != commonpb.EllipticCurveType_CURVE25519.String() { 75 return nil, errors.New("extractPrivKey: invalid key curve") 76 } 77 78 return pbKey.KeyValue, nil 79 } 80 81 return nil, fmt.Errorf("extractPrivKey: can't extract unsupported private key '%s'", primaryKey.KeyData.TypeUrl) 82 } 83 84 func hybridECPrivToECDSAKey(hybridEcPriv *hybrid.ECPrivateKey) *ecdsa.PrivateKey { 85 return &ecdsa.PrivateKey{ 86 PublicKey: ecdsa.PublicKey{ 87 Curve: hybridEcPriv.PublicKey.Curve, 88 X: hybridEcPriv.PublicKey.Point.X, 89 Y: hybridEcPriv.PublicKey.Point.Y, 90 }, 91 D: hybridEcPriv.D, 92 } 93 } 94 95 type noopAEAD struct{} 96 97 func (n noopAEAD) Encrypt(plaintext, additionalData []byte) ([]byte, error) { 98 return plaintext, nil 99 } 100 101 func (n noopAEAD) Decrypt(ciphertext, additionalData []byte) ([]byte, error) { 102 return ciphertext, nil 103 } 104 105 type privKeyWriter struct { 106 w io.Writer 107 } 108 109 // Write writes the public keyset to the underlying w.Writer. It's not used in this implementation. 110 func (p *privKeyWriter) Write(_ *tinkpb.Keyset) error { 111 return fmt.Errorf("privKeyWriter: write function not supported") 112 } 113 114 // WriteEncrypted writes the encrypted keyset to the underlying w.Writer. 115 func (p *privKeyWriter) WriteEncrypted(ks *tinkpb.EncryptedKeyset) error { 116 return write(p.w, ks) 117 } 118 119 func write(w io.Writer, ks *tinkpb.EncryptedKeyset) error { 120 // we write EncryptedKeyset directly without decryption since noopAEAD was used to write *keyset.Handle 121 _, e := w.Write(ks.EncryptedKeyset) 122 return e 123 }