github.com/trustbloc/kms-go@v1.1.2/crypto/tinkcrypto/primitive/secp256k1/secp256k1_signer_key_manager.go (about)

     1  /*
     2  Copyright SecureKey Technologies Inc. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package secp256k1
     8  
     9  import (
    10  	"crypto/ecdsa"
    11  	"crypto/rand"
    12  	"errors"
    13  	"fmt"
    14  
    15  	"github.com/btcsuite/btcd/btcec/v2"
    16  	"github.com/google/tink/go/keyset"
    17  	commonpb "github.com/google/tink/go/proto/common_go_proto"
    18  	tinkpb "github.com/google/tink/go/proto/tink_go_proto"
    19  	"google.golang.org/protobuf/proto"
    20  
    21  	secp256k1pb "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/proto/secp256k1_go_proto"
    22  	subtleSignature "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/secp256k1/subtle"
    23  )
    24  
    25  const (
    26  	secp256k1SignerKeyVersion = 0
    27  	secp256k1SignerTypeURL    = "type.googleapis.com/google.crypto.tink.secp256k1PrivateKey"
    28  )
    29  
    30  // common errors.
    31  var (
    32  	errInvalidSECP256K1SignKey       = errors.New("secp256k1_signer_key_manager: invalid key")
    33  	errInvalidSECP256K1SignKeyFormat = errors.New("secp256k1_signer_key_manager: invalid key format")
    34  )
    35  
    36  // secp256k1SignerKeyManager is an implementation of KeyManager interface.
    37  // It generates new Secp256K1PrivateKeys and produces new instances of ECDSASign subtle.
    38  type secp256k1SignerKeyManager struct{}
    39  
    40  // newSecp256K2SignerKeyManager creates a new secp256k1SignerKeyManager.
    41  func newSecp256K2SignerKeyManager() *secp256k1SignerKeyManager {
    42  	return new(secp256k1SignerKeyManager)
    43  }
    44  
    45  // Primitive creates an ECDSASign subtle for the given serialized ECDSAPrivateKey proto.
    46  func (km *secp256k1SignerKeyManager) Primitive(serializedKey []byte) (interface{}, error) {
    47  	if len(serializedKey) == 0 {
    48  		return nil, errInvalidSECP256K1SignKey
    49  	}
    50  
    51  	key := new(secp256k1pb.Secp256K1PrivateKey)
    52  	if err := proto.Unmarshal(serializedKey, key); err != nil {
    53  		return nil, errInvalidSECP256K1SignKey
    54  	}
    55  
    56  	if err := km.validateKey(key); err != nil {
    57  		return nil, err
    58  	}
    59  
    60  	hash, curve, encoding := getSecp256K1ParamNames(key.PublicKey.Params)
    61  
    62  	ret, err := subtleSignature.NewSecp256K1Signer(hash, curve, encoding, key.KeyValue)
    63  	if err != nil {
    64  		return nil, fmt.Errorf("secp256k1_signer_key_manager: %w", err)
    65  	}
    66  
    67  	return ret, nil
    68  }
    69  
    70  // NewKey creates a new ECDSAPrivateKey according to specification the given serialized ECDSAKeyFormat.
    71  func (km *secp256k1SignerKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) {
    72  	if len(serializedKeyFormat) == 0 {
    73  		return nil, errInvalidSECP256K1SignKeyFormat
    74  	}
    75  
    76  	keyFormat := new(secp256k1pb.Secp256K1KeyFormat)
    77  	if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil {
    78  		return nil, fmt.Errorf("secp256k1_signer_key_manager: invalid proto: %w", err)
    79  	}
    80  
    81  	if err := km.validateKeyFormat(keyFormat); err != nil {
    82  		return nil, fmt.Errorf("secp256k1_signer_key_manager: invalid key format: %w", err)
    83  	}
    84  
    85  	// generate key
    86  	params := keyFormat.Params
    87  
    88  	tmpKey, err := ecdsa.GenerateKey(btcec.S256(), rand.Reader)
    89  	if err != nil {
    90  		return nil, fmt.Errorf("secp256k1_signer_key_manager: cannot generate ECDSA key: %w", err)
    91  	}
    92  
    93  	keyValue := tmpKey.D.Bytes()
    94  	pub := newSecp256K1PublicKey(secp256k1SignerKeyVersion, params, tmpKey.X.Bytes(), tmpKey.Y.Bytes())
    95  	priv := newSecp256K1PrivateKey(secp256k1SignerKeyVersion, pub, keyValue)
    96  
    97  	return priv, nil
    98  }
    99  
   100  // NewKeyData creates a new KeyData according to specification in  the given
   101  // serialized ECDSAKeyFormat. It should be used solely by the key management API.
   102  func (km *secp256k1SignerKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) {
   103  	key, err := km.NewKey(serializedKeyFormat)
   104  	if err != nil {
   105  		return nil, err
   106  	}
   107  
   108  	serializedKey, err := proto.Marshal(key)
   109  	if err != nil {
   110  		return nil, errInvalidSECP256K1SignKeyFormat
   111  	}
   112  
   113  	return &tinkpb.KeyData{
   114  		TypeUrl:         secp256k1SignerTypeURL,
   115  		Value:           serializedKey,
   116  		KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PRIVATE,
   117  	}, nil
   118  }
   119  
   120  // PublicKeyData extracts the public key data from the private key.
   121  func (km *secp256k1SignerKeyManager) PublicKeyData(serializedPrivKey []byte) (*tinkpb.KeyData, error) {
   122  	privKey := new(secp256k1pb.Secp256K1PrivateKey)
   123  	if err := proto.Unmarshal(serializedPrivKey, privKey); err != nil {
   124  		return nil, errInvalidSECP256K1SignKey
   125  	}
   126  
   127  	serializedPubKey, err := proto.Marshal(privKey.PublicKey)
   128  	if err != nil {
   129  		return nil, errInvalidSECP256K1SignKey
   130  	}
   131  
   132  	return &tinkpb.KeyData{
   133  		TypeUrl:         secp256k1VerifierTypeURL,
   134  		Value:           serializedPubKey,
   135  		KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PUBLIC,
   136  	}, nil
   137  }
   138  
   139  // DoesSupport indicates if this key manager supports the given key type.
   140  func (km *secp256k1SignerKeyManager) DoesSupport(typeURL string) bool {
   141  	return typeURL == secp256k1SignerTypeURL
   142  }
   143  
   144  // TypeURL returns the key type of keys managed by this key manager.
   145  func (km *secp256k1SignerKeyManager) TypeURL() string {
   146  	return secp256k1SignerTypeURL
   147  }
   148  
   149  // validateKey validates the given ECDSAPrivateKey.
   150  func (km *secp256k1SignerKeyManager) validateKey(key *secp256k1pb.Secp256K1PrivateKey) error {
   151  	if err := keyset.ValidateKeyVersion(key.Version, secp256k1SignerKeyVersion); err != nil {
   152  		return fmt.Errorf("secp256k1_signer_key_manager: invalid key: %w", err)
   153  	}
   154  
   155  	hash, curve, encoding := getSecp256K1ParamNames(key.PublicKey.Params)
   156  
   157  	return ValidateSecp256K1Params(hash, curve, encoding)
   158  }
   159  
   160  // validateKeyFormat validates the given ECDSAKeyFormat.
   161  func (km *secp256k1SignerKeyManager) validateKeyFormat(format *secp256k1pb.Secp256K1KeyFormat) error {
   162  	hash, curve, encoding := getSecp256K1ParamNames(format.Params)
   163  	return ValidateSecp256K1Params(hash, curve, encoding)
   164  }
   165  
   166  // ValidateSecp256K1Params validates ECDSA parameters.
   167  // The hash's strength must not be weaker than the curve's strength.
   168  // DER and IEEE_P1363 encodings are supported.
   169  func ValidateSecp256K1Params(hashAlg, curve, encoding string) error {
   170  	switch encoding {
   171  	case "Bitcoin_DER":
   172  	case "Bitcoin_IEEE_P1363":
   173  	default:
   174  		return errors.New("secp256k1: unsupported encoding")
   175  	}
   176  
   177  	switch curve {
   178  	case "SECP256K1":
   179  		if hashAlg != "SHA256" {
   180  			return errors.New("invalid hash type for secp256k1 curve, expect SHA-256")
   181  		}
   182  	default:
   183  		return fmt.Errorf("unsupported curve: %s", curve)
   184  	}
   185  
   186  	return nil
   187  }
   188  
   189  // getSecp256K1ParamNames returns the string representations of each parameter in
   190  // the given secp256k1Params.
   191  func getSecp256K1ParamNames(params *secp256k1pb.Secp256K1Params) (string, string, string) {
   192  	hashName := commonpb.HashType_name[int32(params.HashType)]
   193  	curveName := secp256k1pb.BitcoinCurveType_name[int32(params.Curve)]
   194  	encodingName := secp256k1pb.Secp256K1SignatureEncoding_name[int32(params.Encoding)]
   195  
   196  	return hashName, curveName, encodingName
   197  }
   198  
   199  // newSecp256K1PublicKey creates a Secp256K1PublicKey with the specified parameters.
   200  func newSecp256K1PublicKey(version uint32,
   201  	params *secp256k1pb.Secp256K1Params,
   202  	x []byte, y []byte) *secp256k1pb.Secp256K1PublicKey {
   203  	return &secp256k1pb.Secp256K1PublicKey{
   204  		Version: version,
   205  		Params:  params,
   206  		X:       x,
   207  		Y:       y,
   208  	}
   209  }
   210  
   211  // newSecp256K1PrivateKey creates a Secp256K1PrivateKey with the specified parameters.
   212  func newSecp256K1PrivateKey(version uint32,
   213  	publicKey *secp256k1pb.Secp256K1PublicKey,
   214  	keyValue []byte) *secp256k1pb.Secp256K1PrivateKey {
   215  	return &secp256k1pb.Secp256K1PrivateKey{
   216  		Version:   version,
   217  		PublicKey: publicKey,
   218  		KeyValue:  keyValue,
   219  	}
   220  }