github.com/trustbloc/kms-go@v1.1.2/kms/localkms/pubkey_writer.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  	"crypto/ecdsa"
    11  	"crypto/elliptic"
    12  	"crypto/x509"
    13  	"fmt"
    14  	"io"
    15  	"math/big"
    16  
    17  	"github.com/golang/protobuf/proto"
    18  	commonpb "github.com/google/tink/go/proto/common_go_proto"
    19  	ecdsapb "github.com/google/tink/go/proto/ecdsa_go_proto"
    20  	ed25519pb "github.com/google/tink/go/proto/ed25519_go_proto"
    21  	tinkpb "github.com/google/tink/go/proto/tink_go_proto"
    22  	"github.com/google/tink/go/subtle"
    23  
    24  	"github.com/trustbloc/kms-go/spi/kms"
    25  
    26  	"github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/composite/keyio"
    27  	bbspb "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/proto/bbs_go_proto"
    28  	clpb "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/proto/cl_go_proto"
    29  	secp256k1pb "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/proto/secp256k1_go_proto"
    30  	secp256k1subtle "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/secp256k1/subtle"
    31  )
    32  
    33  const (
    34  	ecdsaVerifierTypeURL         = "type.googleapis.com/google.crypto.tink.EcdsaPublicKey"
    35  	ed25519VerifierTypeURL       = "type.googleapis.com/google.crypto.tink.Ed25519PublicKey"
    36  	nistPECDHKWPublicKeyTypeURL  = "type.hyperledger.org/hyperledger.aries.crypto.tink.NistPEcdhKwPublicKey"
    37  	x25519ECDHKWPublicKeyTypeURL = "type.hyperledger.org/hyperledger.aries.crypto.tink.X25519EcdhKwPublicKey"
    38  	bbsVerifierKeyTypeURL        = "type.hyperledger.org/hyperledger.aries.crypto.tink.BBSPublicKey"
    39  	clCredDefKeyTypeURL          = "type.hyperledger.org/hyperledger.aries.crypto.tink.CLCredDefKey"
    40  	secp256k1VerifierTypeURL     = "type.googleapis.com/google.crypto.tink.secp256k1PublicKey"
    41  	derPrefix                    = "der-"
    42  	p13163Prefix                 = "p1363-"
    43  )
    44  
    45  //nolint:gochecknoglobals
    46  var ecdsaKMSKeyTypes = map[string]kms.KeyType{
    47  	derPrefix + "NIST_P256":    kms.ECDSAP256TypeDER,
    48  	derPrefix + "NIST_P384":    kms.ECDSAP384TypeDER,
    49  	derPrefix + "NIST_P521":    kms.ECDSAP521TypeDER,
    50  	derPrefix + "SECP256K1":    kms.ECDSASecp256k1DER,
    51  	p13163Prefix + "NIST_P256": kms.ECDSAP256TypeIEEEP1363,
    52  	p13163Prefix + "NIST_P384": kms.ECDSAP384TypeIEEEP1363,
    53  	p13163Prefix + "NIST_P521": kms.ECDSAP521TypeIEEEP1363,
    54  	p13163Prefix + "SECP256K1": kms.ECDSASecp256k1IEEEP1363,
    55  }
    56  
    57  // PubKeyWriter will write the raw bytes of a Tink KeySet's primary public key
    58  // The keyset must be one of the keyURLs defined above
    59  // Note: Only signing public keys and ecdh key types created in tinkcrypto can be exported through this PubKeyWriter.
    60  // ECHDES has its own Writer to export its public keys due to cyclic dependency.
    61  type PubKeyWriter struct {
    62  	// KeyType is Key Type of the written key. It's needed as Write() is an interface function and can't return it.
    63  	KeyType kms.KeyType
    64  	w       io.Writer
    65  }
    66  
    67  // NewWriter creates a new PubKeyWriter instance.
    68  func NewWriter(w io.Writer) *PubKeyWriter {
    69  	return &PubKeyWriter{
    70  		w: w,
    71  	}
    72  }
    73  
    74  // Write writes the public keyset to the underlying w.Writer.
    75  func (p *PubKeyWriter) Write(keyset *tinkpb.Keyset) error {
    76  	keyType, err := write(p.w, keyset)
    77  	if err != nil {
    78  		return err
    79  	}
    80  
    81  	p.KeyType = keyType
    82  
    83  	return nil
    84  }
    85  
    86  // WriteEncrypted writes the encrypted keyset to the underlying w.Writer.
    87  func (p *PubKeyWriter) WriteEncrypted(keyset *tinkpb.EncryptedKeyset) error {
    88  	return fmt.Errorf("write encrypted function not supported")
    89  }
    90  
    91  func write(w io.Writer, msg *tinkpb.Keyset) (kms.KeyType, error) {
    92  	ks := msg.Key
    93  	primaryKID := msg.PrimaryKeyId
    94  	created := false
    95  
    96  	var (
    97  		kt  kms.KeyType
    98  		err error
    99  	)
   100  
   101  	for _, key := range ks {
   102  		if key.KeyId == primaryKID && key.Status == tinkpb.KeyStatusType_ENABLED {
   103  			switch key.KeyData.TypeUrl {
   104  			case ecdsaVerifierTypeURL, ed25519VerifierTypeURL, bbsVerifierKeyTypeURL, clCredDefKeyTypeURL,
   105  				secp256k1VerifierTypeURL:
   106  				created, kt, err = writePubKey(w, key)
   107  				if err != nil {
   108  					return "", err
   109  				}
   110  			case nistPECDHKWPublicKeyTypeURL, x25519ECDHKWPublicKeyTypeURL:
   111  				pkW := keyio.NewWriter(w)
   112  
   113  				err = pkW.Write(msg)
   114  				if err != nil {
   115  					return "", err
   116  				}
   117  
   118  				kt = pkW.KeyType
   119  				created = true
   120  			default:
   121  				return "", fmt.Errorf("key type not supported for writing raw key bytes: %s", key.KeyData.TypeUrl)
   122  			}
   123  
   124  			break
   125  		}
   126  	}
   127  
   128  	if !created {
   129  		return "", fmt.Errorf("key not written")
   130  	}
   131  
   132  	return kt, nil
   133  }
   134  
   135  // nolint:gocyclo,funlen
   136  func writePubKey(w io.Writer, key *tinkpb.Keyset_Key) (bool, kms.KeyType, error) {
   137  	var (
   138  		marshaledRawPubKey []byte
   139  		kt                 kms.KeyType
   140  	)
   141  
   142  	// TODO add other key types than the ones below and other than nistPECDHKWPublicKeyTypeURL and
   143  	// TODO x25519ECDHKWPublicKeyTypeURL(eg: secp256k1 when introduced in KMS).
   144  	switch key.KeyData.TypeUrl {
   145  	case ecdsaVerifierTypeURL:
   146  		pubKeyProto := new(ecdsapb.EcdsaPublicKey)
   147  
   148  		err := proto.Unmarshal(key.KeyData.Value, pubKeyProto)
   149  		if err != nil {
   150  			return false, "", err
   151  		}
   152  
   153  		marshaledRawPubKey, kt, err = getMarshalledECDSAKeyValueFromProto(pubKeyProto)
   154  		if err != nil {
   155  			return false, "", err
   156  		}
   157  	case ed25519VerifierTypeURL:
   158  		pubKeyProto := new(ed25519pb.Ed25519PublicKey)
   159  
   160  		err := proto.Unmarshal(key.KeyData.Value, pubKeyProto)
   161  		if err != nil {
   162  			return false, "", err
   163  		}
   164  
   165  		marshaledRawPubKey = make([]byte, len(pubKeyProto.KeyValue))
   166  		copy(marshaledRawPubKey, pubKeyProto.KeyValue)
   167  
   168  		kt = kms.ED25519Type
   169  	case bbsVerifierKeyTypeURL:
   170  		pubKeyProto := new(bbspb.BBSPublicKey)
   171  
   172  		err := proto.Unmarshal(key.KeyData.Value, pubKeyProto)
   173  		if err != nil {
   174  			return false, "", err
   175  		}
   176  
   177  		marshaledRawPubKey = make([]byte, len(pubKeyProto.KeyValue))
   178  		copy(marshaledRawPubKey, pubKeyProto.KeyValue)
   179  
   180  		kt = kms.BLS12381G2Type
   181  	case clCredDefKeyTypeURL:
   182  		pubKeyProto := new(clpb.CLCredDefPublicKey)
   183  
   184  		err := proto.Unmarshal(key.KeyData.Value, pubKeyProto)
   185  		if err != nil {
   186  			return false, "", err
   187  		}
   188  
   189  		marshaledRawPubKey = make([]byte, len(pubKeyProto.KeyValue))
   190  		copy(marshaledRawPubKey, pubKeyProto.KeyValue)
   191  
   192  		kt = kms.CLCredDefType
   193  	case secp256k1VerifierTypeURL:
   194  		pubKeyProto := new(secp256k1pb.Secp256K1PublicKey)
   195  
   196  		err := proto.Unmarshal(key.KeyData.Value, pubKeyProto)
   197  		if err != nil {
   198  			return false, "", err
   199  		}
   200  
   201  		marshaledRawPubKey, kt, err = getMarshalledSecp256K1KeyValueFromProto(pubKeyProto)
   202  		if err != nil {
   203  			return false, "", err
   204  		}
   205  	default:
   206  		return false, "", fmt.Errorf("can't export key with keyURL:%s", key.KeyData.TypeUrl)
   207  	}
   208  
   209  	n, err := w.Write(marshaledRawPubKey)
   210  	if err != nil {
   211  		return false, "", nil //nolint:nilerr
   212  	}
   213  
   214  	return n > 0, kt, nil
   215  }
   216  
   217  func getMarshalledECDSAKeyValueFromProto(pubKeyProto *ecdsapb.EcdsaPublicKey) ([]byte, kms.KeyType, error) {
   218  	var (
   219  		marshaledRawPubKey []byte
   220  		err                error
   221  		kt                 kms.KeyType
   222  	)
   223  
   224  	curveName := commonpb.EllipticCurveType_name[int32(pubKeyProto.Params.Curve)]
   225  
   226  	curve := subtle.GetCurve(curveName)
   227  	if curve == nil {
   228  		return nil, "", fmt.Errorf("undefined curve")
   229  	}
   230  
   231  	pubKey := ecdsa.PublicKey{
   232  		Curve: curve,
   233  		X:     new(big.Int),
   234  		Y:     new(big.Int),
   235  	}
   236  
   237  	pubKey.X.SetBytes(pubKeyProto.X)
   238  	pubKey.Y.SetBytes(pubKeyProto.Y)
   239  
   240  	switch pubKeyProto.Params.Encoding {
   241  	case ecdsapb.EcdsaSignatureEncoding_DER:
   242  		marshaledRawPubKey, err = x509.MarshalPKIXPublicKey(&pubKey) // DER format not supported here.
   243  		if err != nil {
   244  			return nil, "", err
   245  		}
   246  
   247  		kt = ecdsaKMSKeyTypes[derPrefix+curveName]
   248  	case ecdsapb.EcdsaSignatureEncoding_IEEE_P1363:
   249  		marshaledRawPubKey = elliptic.Marshal(curve, pubKey.X, pubKey.Y)
   250  		kt = ecdsaKMSKeyTypes[p13163Prefix+curveName]
   251  	default:
   252  		return nil, "", fmt.Errorf("can't export key with bad key encoding: '%s'", pubKeyProto.Params.Encoding)
   253  	}
   254  
   255  	return marshaledRawPubKey, kt, nil
   256  }
   257  
   258  func getMarshalledSecp256K1KeyValueFromProto(pkPB *secp256k1pb.Secp256K1PublicKey) ([]byte, kms.KeyType, error) {
   259  	var (
   260  		marshaledRawPubKey []byte
   261  		err                error
   262  		kt                 kms.KeyType
   263  	)
   264  
   265  	curveName := secp256k1pb.BitcoinCurveType_name[int32(pkPB.Params.Curve)]
   266  
   267  	curve := secp256k1subtle.GetCurve(curveName)
   268  	if curve == nil {
   269  		return nil, "", fmt.Errorf("undefined curve")
   270  	}
   271  
   272  	pubKey := ecdsa.PublicKey{
   273  		Curve: curve,
   274  		X:     new(big.Int),
   275  		Y:     new(big.Int),
   276  	}
   277  
   278  	pubKey.X.SetBytes(pkPB.X)
   279  	pubKey.Y.SetBytes(pkPB.Y)
   280  
   281  	switch pkPB.Params.Encoding {
   282  	case secp256k1pb.Secp256K1SignatureEncoding_Bitcoin_DER:
   283  		marshaledRawPubKey, err = x509.MarshalPKIXPublicKey(&pubKey)
   284  		if err != nil {
   285  			return nil, "", err
   286  		}
   287  
   288  		kt = ecdsaKMSKeyTypes[derPrefix+curveName]
   289  	case secp256k1pb.Secp256K1SignatureEncoding_Bitcoin_IEEE_P1363:
   290  		marshaledRawPubKey = elliptic.Marshal(curve, pubKey.X, pubKey.Y)
   291  		kt = ecdsaKMSKeyTypes[p13163Prefix+curveName]
   292  	default:
   293  		return nil, "", fmt.Errorf("can't export key with bad key encoding: '%s'", pkPB.Params.Encoding)
   294  	}
   295  
   296  	return marshaledRawPubKey, kt, nil
   297  }