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 }