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  }