github.com/trustbloc/kms-go@v1.1.2/kms/localkms/privkey_import.go (about)

     1  /*
     2  Copyright SecureKey Technologies Inc. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package localkms
     8  
     9  import (
    10  	"bytes"
    11  	"crypto/ecdsa"
    12  	"crypto/ed25519"
    13  	"fmt"
    14  
    15  	"github.com/golang/protobuf/proto"
    16  	"github.com/google/tink/go/keyset"
    17  	commonpb "github.com/google/tink/go/proto/common_go_proto"
    18  	ecdsapb "github.com/google/tink/go/proto/ecdsa_go_proto"
    19  	ed25519pb "github.com/google/tink/go/proto/ed25519_go_proto"
    20  	tinkpb "github.com/google/tink/go/proto/tink_go_proto"
    21  	"github.com/trustbloc/bbs-signature-go/bbs12381g2pub"
    22  
    23  	"github.com/trustbloc/kms-go/spi/kms"
    24  
    25  	"github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/composite/ecdh"
    26  	bbspb "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/proto/bbs_go_proto"
    27  	clpb "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/proto/cl_go_proto"
    28  	ecdhpb "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/proto/ecdh_aead_go_proto"
    29  	secp256k1pb "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/proto/secp256k1_go_proto"
    30  )
    31  
    32  const (
    33  	ecdsaSignerTypeURL           = "type.googleapis.com/google.crypto.tink.EcdsaPrivateKey"
    34  	ed25519SignerTypeURL         = "type.googleapis.com/google.crypto.tink.Ed25519PrivateKey"
    35  	bbsSignerKeyTypeURL          = "type.hyperledger.org/hyperledger.aries.crypto.tink.BBSPrivateKey"
    36  	secp256k1SignerTypeURL       = "type.googleapis.com/google.crypto.tink.secp256k1PrivateKey"
    37  	nistpECDHKWPrivateKeyTypeURL = "type.hyperledger.org/hyperledger.aries.crypto.tink.NistPEcdhKwPrivateKey"
    38  )
    39  
    40  //nolint:funlen,gocyclo
    41  func (l *LocalKMS) importECDSAKey(privKey *ecdsa.PrivateKey, kt kms.KeyType,
    42  	opts ...kms.PrivateKeyOpts) (string, *keyset.Handle, error) {
    43  	var params *ecdsapb.EcdsaParams
    44  
    45  	err := validECPrivateKey(privKey)
    46  	if err != nil {
    47  		return "", nil, fmt.Errorf("import private EC key failed: %w", err)
    48  	}
    49  
    50  	switch kt {
    51  	case kms.NISTP256ECDHKWType, kms.NISTP384ECDHKWType, kms.NISTP521ECDHKWType:
    52  		return l.buildAndImportECDSAPrivateKeyAsECDHKW(privKey, kt, opts...)
    53  	case kms.ECDSAP256TypeDER:
    54  		params = &ecdsapb.EcdsaParams{
    55  			Curve:    commonpb.EllipticCurveType_NIST_P256,
    56  			Encoding: ecdsapb.EcdsaSignatureEncoding_DER,
    57  			HashType: commonpb.HashType_SHA256,
    58  		}
    59  	case kms.ECDSAP384TypeDER:
    60  		params = &ecdsapb.EcdsaParams{
    61  			Curve:    commonpb.EllipticCurveType_NIST_P384,
    62  			Encoding: ecdsapb.EcdsaSignatureEncoding_DER,
    63  			HashType: commonpb.HashType_SHA384,
    64  		}
    65  	case kms.ECDSAP521TypeDER:
    66  		params = &ecdsapb.EcdsaParams{
    67  			Curve:    commonpb.EllipticCurveType_NIST_P521,
    68  			Encoding: ecdsapb.EcdsaSignatureEncoding_DER,
    69  			HashType: commonpb.HashType_SHA512,
    70  		}
    71  	case kms.ECDSAP256TypeIEEEP1363:
    72  		params = &ecdsapb.EcdsaParams{
    73  			Curve:    commonpb.EllipticCurveType_NIST_P256,
    74  			Encoding: ecdsapb.EcdsaSignatureEncoding_IEEE_P1363,
    75  			HashType: commonpb.HashType_SHA256,
    76  		}
    77  	case kms.ECDSAP384TypeIEEEP1363:
    78  		params = &ecdsapb.EcdsaParams{
    79  			Curve:    commonpb.EllipticCurveType_NIST_P384,
    80  			Encoding: ecdsapb.EcdsaSignatureEncoding_IEEE_P1363,
    81  			HashType: commonpb.HashType_SHA384,
    82  		}
    83  	case kms.ECDSAP521TypeIEEEP1363:
    84  		params = &ecdsapb.EcdsaParams{
    85  			Curve:    commonpb.EllipticCurveType_NIST_P521,
    86  			Encoding: ecdsapb.EcdsaSignatureEncoding_IEEE_P1363,
    87  			HashType: commonpb.HashType_SHA512,
    88  		}
    89  	case kms.ECDSASecp256k1DER:
    90  		return l.importSecp256K1Key(privKey, &secp256k1pb.Secp256K1Params{
    91  			HashType: commonpb.HashType_SHA256,
    92  			Curve:    secp256k1pb.BitcoinCurveType_SECP256K1,
    93  			Encoding: secp256k1pb.Secp256K1SignatureEncoding_Bitcoin_DER,
    94  		})
    95  	case kms.ECDSASecp256k1IEEEP1363:
    96  		return l.importSecp256K1Key(privKey, &secp256k1pb.Secp256K1Params{
    97  			HashType: commonpb.HashType_SHA256,
    98  			Curve:    secp256k1pb.BitcoinCurveType_SECP256K1,
    99  			Encoding: secp256k1pb.Secp256K1SignatureEncoding_Bitcoin_IEEE_P1363,
   100  		})
   101  	default:
   102  		return "", nil, fmt.Errorf("import private EC key failed: invalid ECDSA key type")
   103  	}
   104  
   105  	mKeyValue, err := getMarshalledECDSAPrivateKey(privKey, params)
   106  	if err != nil {
   107  		return "", nil, fmt.Errorf("import private EC key failed: %w", err)
   108  	}
   109  
   110  	ks := newKeySet(ecdsaSignerTypeURL, mKeyValue, tinkpb.KeyData_ASYMMETRIC_PRIVATE)
   111  
   112  	return l.importKeySet(ks, opts...)
   113  }
   114  
   115  func (l *LocalKMS) importSecp256K1Key(privKey *ecdsa.PrivateKey, params *secp256k1pb.Secp256K1Params,
   116  	opts ...kms.PrivateKeyOpts) (string, *keyset.Handle, error) {
   117  	mKeyValue, err := getMarshalledECDSASecp256K1PrivateKey(privKey, params)
   118  	if err != nil {
   119  		return "", nil, fmt.Errorf("import private EC secp256k1 key failed: %w", err)
   120  	}
   121  
   122  	ks := newKeySet(secp256k1SignerTypeURL, mKeyValue, tinkpb.KeyData_ASYMMETRIC_PRIVATE)
   123  
   124  	return l.importKeySet(ks, opts...)
   125  }
   126  
   127  func (l *LocalKMS) buildAndImportECDSAPrivateKeyAsECDHKW(privKey *ecdsa.PrivateKey, kt kms.KeyType,
   128  	opts ...kms.PrivateKeyOpts) (string, *keyset.Handle, error) {
   129  	var keyTemplate *tinkpb.KeyTemplate
   130  
   131  	switch kt {
   132  	case kms.NISTP256ECDHKWType:
   133  		keyTemplate = ecdh.NISTP256ECDHKWKeyTemplate()
   134  	case kms.NISTP384ECDHKWType:
   135  		keyTemplate = ecdh.NISTP384ECDHKWKeyTemplate()
   136  	case kms.NISTP521ECDHKWType:
   137  		keyTemplate = ecdh.NISTP521ECDHKWKeyTemplate()
   138  	}
   139  
   140  	keyFormat := new(ecdhpb.EcdhAeadKeyFormat)
   141  
   142  	err := proto.Unmarshal(keyTemplate.Value, keyFormat)
   143  	if err != nil {
   144  		return "", nil, fmt.Errorf("invalid key format")
   145  	}
   146  
   147  	priv := &ecdhpb.EcdhAeadPrivateKey{
   148  		Version:  0,
   149  		KeyValue: privKey.D.Bytes(),
   150  		PublicKey: &ecdhpb.EcdhAeadPublicKey{
   151  			Version: 0,
   152  			Params:  keyFormat.Params,
   153  			X:       privKey.PublicKey.X.Bytes(),
   154  			Y:       privKey.PublicKey.Y.Bytes(),
   155  		},
   156  	}
   157  
   158  	privBytes, err := proto.Marshal(priv)
   159  	if err != nil {
   160  		return "", nil, fmt.Errorf("marshal protobuf: %w", err)
   161  	}
   162  
   163  	ks := newKeySet(nistpECDHKWPrivateKeyTypeURL, privBytes, tinkpb.KeyData_ASYMMETRIC_PRIVATE)
   164  
   165  	return l.importKeySet(ks, opts...)
   166  }
   167  
   168  func (l *LocalKMS) importKeySet(ks *tinkpb.Keyset, opts ...kms.PrivateKeyOpts) (string, *keyset.Handle, error) {
   169  	ksID, err := l.writeImportedKey(ks, opts...)
   170  	if err != nil {
   171  		return "", nil, fmt.Errorf("import private EC key failed: %w", err)
   172  	}
   173  
   174  	kh, err := l.getKeySet(ksID)
   175  	if err != nil {
   176  		return ksID, nil, fmt.Errorf("import private EC key successful but failed to get key from store: %w", err)
   177  	}
   178  
   179  	return ksID, kh, nil
   180  }
   181  
   182  func getMarshalledECDSAPrivateKey(privKey *ecdsa.PrivateKey, params *ecdsapb.EcdsaParams) ([]byte, error) {
   183  	pubKeyProto := newProtoECDSAPublicKey(&privKey.PublicKey, params)
   184  	return proto.Marshal(newProtoECDSAPrivateKey(pubKeyProto, privKey.D.Bytes()))
   185  }
   186  
   187  func getMarshalledECDSASecp256K1PrivateKey(privKey *ecdsa.PrivateKey,
   188  	params *secp256k1pb.Secp256K1Params) ([]byte, error) {
   189  	pubKeyProto := newProtoSecp256K1PublicKey(&privKey.PublicKey, params)
   190  	return proto.Marshal(newProtoECDSASecp256K1PrivateKey(pubKeyProto, privKey.D.Bytes()))
   191  }
   192  
   193  func (l *LocalKMS) importEd25519Key(privKey ed25519.PrivateKey, kt kms.KeyType,
   194  	opts ...kms.PrivateKeyOpts) (string, *keyset.Handle, error) {
   195  	if privKey == nil {
   196  		return "", nil, fmt.Errorf("import private ED25519 key failed: private key is nil")
   197  	}
   198  
   199  	if kt != kms.ED25519Type {
   200  		return "", nil, fmt.Errorf("import private ED25519 key failed: invalid key type")
   201  	}
   202  
   203  	privKeyProto, err := newProtoEd25519PrivateKey(privKey)
   204  	if err != nil {
   205  		return "", nil, fmt.Errorf("import private ED25519 key failed: %w", err)
   206  	}
   207  
   208  	mKeyValue, err := proto.Marshal(privKeyProto)
   209  	if err != nil {
   210  		return "", nil, fmt.Errorf("import private ED25519 key failed: %w", err)
   211  	}
   212  
   213  	ks := newKeySet(ed25519SignerTypeURL, mKeyValue, tinkpb.KeyData_ASYMMETRIC_PRIVATE)
   214  
   215  	return l.importKeySet(ks, opts...)
   216  }
   217  
   218  func (l *LocalKMS) importBBSKey(privKey *bbs12381g2pub.PrivateKey, kt kms.KeyType,
   219  	opts ...kms.PrivateKeyOpts) (string, *keyset.Handle, error) {
   220  	if privKey == nil {
   221  		return "", nil, fmt.Errorf("import private BBS+ key failed: private key is nil")
   222  	}
   223  
   224  	if kt != kms.BLS12381G2Type {
   225  		return "", nil, fmt.Errorf("import private BBS+ key failed: invalid key type")
   226  	}
   227  
   228  	privKeyProto, err := newProtoBBSPrivateKey(privKey, kt)
   229  	if err != nil {
   230  		return "", nil, fmt.Errorf("import private BBS+ key failed: %w", err)
   231  	}
   232  
   233  	mKeyValue, err := proto.Marshal(privKeyProto)
   234  	if err != nil {
   235  		return "", nil, fmt.Errorf("import private BBS+ key failed: %w", err)
   236  	}
   237  
   238  	ks := newKeySet(bbsSignerKeyTypeURL, mKeyValue, tinkpb.KeyData_ASYMMETRIC_PRIVATE)
   239  
   240  	return l.importKeySet(ks, opts...)
   241  }
   242  
   243  func validECPrivateKey(privateKey *ecdsa.PrivateKey) error {
   244  	if privateKey == nil {
   245  		return fmt.Errorf("private key is nil")
   246  	}
   247  
   248  	if privateKey.X == nil {
   249  		return fmt.Errorf("private key's public key is missing x coordinate")
   250  	}
   251  
   252  	if privateKey.Y == nil {
   253  		return fmt.Errorf("private key's public key is missing y coordinate")
   254  	}
   255  
   256  	if privateKey.D == nil {
   257  		return fmt.Errorf("private key data is missing")
   258  	}
   259  
   260  	return nil
   261  }
   262  
   263  // newProtoECDSAPrivateKey creates a ECDSAPrivateKey with the specified parameters.
   264  func newProtoECDSAPrivateKey(publicKey *ecdsapb.EcdsaPublicKey, keyValue []byte) *ecdsapb.EcdsaPrivateKey {
   265  	return &ecdsapb.EcdsaPrivateKey{
   266  		Version:   0,
   267  		PublicKey: publicKey,
   268  		KeyValue:  keyValue,
   269  	}
   270  }
   271  
   272  // newProtoECDSASecp256K1PrivateKey creates a Secp256K1PrivateKey with the specified parameters.
   273  func newProtoECDSASecp256K1PrivateKey(publicKey *secp256k1pb.Secp256K1PublicKey,
   274  	keyValue []byte) *secp256k1pb.Secp256K1PrivateKey {
   275  	return &secp256k1pb.Secp256K1PrivateKey{
   276  		Version:   0,
   277  		PublicKey: publicKey,
   278  		KeyValue:  keyValue,
   279  	}
   280  }
   281  
   282  func newProtoEd25519PrivateKey(privateKey ed25519.PrivateKey) (*ed25519pb.Ed25519PrivateKey, error) {
   283  	pubKey, ok := (privateKey.Public()).(ed25519.PublicKey)
   284  	if !ok {
   285  		return nil, fmt.Errorf("public key from private key is not ed25519.PublicKey")
   286  	}
   287  
   288  	publicProto := &ed25519pb.Ed25519PublicKey{
   289  		Version:  0,
   290  		KeyValue: pubKey,
   291  	}
   292  
   293  	return &ed25519pb.Ed25519PrivateKey{
   294  		Version:   0,
   295  		PublicKey: publicProto,
   296  		KeyValue:  privateKey.Seed(),
   297  	}, nil
   298  }
   299  
   300  func newProtoBBSPrivateKey(privateKey *bbs12381g2pub.PrivateKey, kt kms.KeyType) (*bbspb.BBSPrivateKey, error) {
   301  	publicKey := privateKey.PublicKey()
   302  
   303  	pubKeyBytes, err := publicKey.Marshal()
   304  	if err != nil {
   305  		return nil, err
   306  	}
   307  
   308  	publicProto := &bbspb.BBSPublicKey{
   309  		Version:  0,
   310  		Params:   buidBBSParams(kt),
   311  		KeyValue: pubKeyBytes,
   312  	}
   313  
   314  	privKeyBytes, err := privateKey.Marshal()
   315  	if err != nil {
   316  		return nil, err
   317  	}
   318  
   319  	return &bbspb.BBSPrivateKey{
   320  		Version:   0,
   321  		PublicKey: publicProto,
   322  		KeyValue:  privKeyBytes,
   323  	}, nil
   324  }
   325  
   326  func buidBBSParams(kt kms.KeyType) *bbspb.BBSParams {
   327  	if kt == kms.BLS12381G2Type {
   328  		return &bbspb.BBSParams{
   329  			HashType: commonpb.HashType_SHA256,
   330  			Curve:    bbspb.BBSCurveType_BLS12_381,
   331  			Group:    bbspb.GroupField_G2,
   332  		}
   333  	}
   334  
   335  	return nil
   336  }
   337  
   338  func buidCLCredDefParams(kt kms.KeyType, opts ...kms.KeyOpts) *clpb.CLCredDefParams {
   339  	if kt == kms.CLCredDefType {
   340  		keyOpts := kms.NewKeyOpt()
   341  
   342  		for _, opt := range opts {
   343  			opt(keyOpts)
   344  		}
   345  
   346  		return &clpb.CLCredDefParams{
   347  			Attrs: keyOpts.Attrs(),
   348  		}
   349  	}
   350  
   351  	return nil
   352  }
   353  
   354  func (l *LocalKMS) writeImportedKey(ks *tinkpb.Keyset, opts ...kms.PrivateKeyOpts) (string, error) {
   355  	serializedKeyset, err := proto.Marshal(ks)
   356  	if err != nil {
   357  		return "", fmt.Errorf("invalid keyset data")
   358  	}
   359  
   360  	encrypted, err := l.primaryKeyEnvAEAD.Encrypt(serializedKeyset, []byte{})
   361  	if err != nil {
   362  		return "", fmt.Errorf("encrypted failed: %w", err)
   363  	}
   364  
   365  	ksInfo, err := getKeysetInfo(ks)
   366  	if err != nil {
   367  		return "", fmt.Errorf("cannot get keyset info: %w", err)
   368  	}
   369  
   370  	encryptedKeyset := &tinkpb.EncryptedKeyset{
   371  		EncryptedKeyset: encrypted,
   372  		KeysetInfo:      ksInfo,
   373  	}
   374  
   375  	buf := new(bytes.Buffer)
   376  	jsonKeysetWriter := keyset.NewJSONWriter(buf)
   377  
   378  	err = jsonKeysetWriter.WriteEncrypted(encryptedKeyset)
   379  	if err != nil {
   380  		return "", fmt.Errorf("failed to write keyset as json: %w", err)
   381  	}
   382  
   383  	return writeToStore(l.store, buf, opts...)
   384  }
   385  
   386  func getKeysetInfo(ks *tinkpb.Keyset) (*tinkpb.KeysetInfo, error) {
   387  	if ks == nil {
   388  		return nil, fmt.Errorf("keyset is nil")
   389  	}
   390  
   391  	var keyInfos []*tinkpb.KeysetInfo_KeyInfo
   392  
   393  	for _, key := range ks.Key {
   394  		info, err := getKeyInfo(key)
   395  		if err != nil {
   396  			return nil, err
   397  		}
   398  
   399  		keyInfos = append(keyInfos, info)
   400  	}
   401  
   402  	return &tinkpb.KeysetInfo{
   403  		PrimaryKeyId: ks.PrimaryKeyId,
   404  		KeyInfo:      keyInfos,
   405  	}, nil
   406  }
   407  
   408  func getKeyInfo(key *tinkpb.Keyset_Key) (*tinkpb.KeysetInfo_KeyInfo, error) {
   409  	if key == nil {
   410  		return nil, fmt.Errorf("keyset key is nil")
   411  	}
   412  
   413  	return &tinkpb.KeysetInfo_KeyInfo{
   414  		TypeUrl:          key.KeyData.TypeUrl,
   415  		Status:           key.Status,
   416  		KeyId:            key.KeyId,
   417  		OutputPrefixType: key.OutputPrefixType,
   418  	}, nil
   419  }