github.com/hashgraph/hedera-sdk-go/v2@v2.48.0/ecdsa_private_key.go (about) 1 package hedera 2 3 /*- 4 * 5 * Hedera Go SDK 6 * 7 * Copyright (C) 2020 - 2024 Hedera Hashgraph, LLC 8 * 9 * Licensed under the Apache License, Version 2.0 (the "License"); 10 * you may not use this file except in compliance with the License. 11 * You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 * 21 */ 22 23 import ( 24 "crypto/ecdsa" 25 "crypto/hmac" 26 "crypto/rand" 27 "crypto/sha512" 28 "crypto/x509" 29 "encoding/asn1" 30 "encoding/hex" 31 "encoding/pem" 32 "fmt" 33 "io" 34 "strings" 35 36 "github.com/ethereum/go-ethereum/crypto" 37 "github.com/hashgraph/hedera-protobufs-go/services" 38 "github.com/pkg/errors" 39 ) 40 41 // _ECDSAPrivateKey is an Key_ECDSASecp256K1 private key. 42 type _ECDSAPrivateKey struct { 43 keyData *ecdsa.PrivateKey 44 chainCode []byte 45 } 46 47 const _LegacyECDSAPrivateKeyPrefix = "3030020100300706052b8104000a04220420" 48 49 func _GenerateECDSAPrivateKey() (*_ECDSAPrivateKey, error) { 50 key, err := ecdsa.GenerateKey(crypto.S256(), rand.Reader) 51 if err != nil { 52 return &_ECDSAPrivateKey{}, err 53 } 54 55 return &_ECDSAPrivateKey{ 56 keyData: key, 57 }, nil 58 } 59 60 func _ECDSAPrivateKeyFromBytes(byt []byte) (*_ECDSAPrivateKey, error) { 61 length := len(byt) 62 switch { 63 case length == 32: 64 return _ECDSAPrivateKeyFromBytesRaw(byt) 65 case length > 32: 66 return _ECDSAPrivateKeyFromBytesDer(byt) 67 default: 68 return &_ECDSAPrivateKey{}, _NewErrBadKeyf("invalid private key length: %v bytes", len(byt)) 69 } 70 } 71 72 func _ECDSAPrivateKeyFromBytesRaw(byt []byte) (*_ECDSAPrivateKey, error) { 73 length := len(byt) 74 if length != 32 { 75 return &_ECDSAPrivateKey{}, _NewErrBadKeyf("invalid private key length: %v bytes", len(byt)) 76 } 77 78 key, err := crypto.ToECDSA(byt) 79 if err != nil { 80 return nil, err 81 } 82 83 return &_ECDSAPrivateKey{ 84 keyData: key, 85 }, nil 86 } 87 88 func _LegacyECDSAPrivateKeyFromBytesDer(byt []byte) (*_ECDSAPrivateKey, error) { 89 given := hex.EncodeToString(byt) 90 91 result := strings.ReplaceAll(given, _LegacyECDSAPrivateKeyPrefix, "") 92 decoded, err := hex.DecodeString(result) 93 if err != nil { 94 return &_ECDSAPrivateKey{}, err 95 } 96 97 if len(decoded) != 32 { 98 return &_ECDSAPrivateKey{}, _NewErrBadKeyf("invalid private key length: %v bytes", len(byt)) 99 } 100 101 key, err := crypto.ToECDSA(decoded) 102 if err != nil { 103 return nil, err 104 } 105 106 return &_ECDSAPrivateKey{ 107 keyData: key, 108 }, nil 109 } 110 111 func _ECDSAPrivateKeyFromBytesDer(data []byte) (*_ECDSAPrivateKey, error) { 112 given := hex.EncodeToString(data) 113 if strings.HasPrefix(given, _LegacyECDSAPrivateKeyPrefix) { 114 return _LegacyECDSAPrivateKeyFromBytesDer(data) 115 } 116 117 type ECPrivateKey struct { 118 Version int 119 PrivateKey []byte 120 NamedCurveOID asn1.ObjectIdentifier `asn1:"optional,explicit,tag:0"` 121 PublicKey asn1.BitString `asn1:"optional,explicit,tag:1"` 122 } 123 var ecKey ECPrivateKey 124 if rest, err := asn1.Unmarshal(data, &ecKey); err != nil { 125 return nil, err 126 } else if len(rest) != 0 { 127 return nil, errors.New("x509: trailing data after ASN.1 of public-key") 128 } 129 key, err := crypto.ToECDSA(ecKey.PrivateKey) 130 if err != nil { 131 return nil, err 132 } 133 return &_ECDSAPrivateKey{keyData: key}, nil 134 } 135 136 func _ECDSAPrivateKeyFromSeed(seed []byte) (*_ECDSAPrivateKey, error) { 137 h := hmac.New(sha512.New, []byte("Bitcoin seed")) 138 139 _, err := h.Write(seed) 140 if err != nil { 141 return &_ECDSAPrivateKey{}, err 142 } 143 144 digest := h.Sum(nil) 145 146 keyBytes := digest[0:32] 147 chainCode := digest[32:] 148 privateKey, err := _ECDSAPrivateKeyFromBytes(keyBytes) 149 150 if err != nil { 151 return &_ECDSAPrivateKey{}, err 152 } 153 privateKey.chainCode = chainCode 154 155 return privateKey, nil 156 } 157 158 func _ECDSAPrivateKeyFromString(s string) (*_ECDSAPrivateKey, error) { 159 b, err := hex.DecodeString(strings.ToLower(s)) 160 if err != nil { 161 return &_ECDSAPrivateKey{}, err 162 } 163 164 return _ECDSAPrivateKeyFromBytes(b) 165 } 166 167 func (sk _ECDSAPrivateKey) _PublicKey() *_ECDSAPublicKey { 168 if sk.keyData.Y == nil && sk.keyData.X == nil { 169 b := sk.keyData.D.Bytes() 170 x, y := crypto.S256().ScalarBaseMult(b) 171 sk.keyData.X = x 172 sk.keyData.Y = y 173 return &_ECDSAPublicKey{ 174 &ecdsa.PublicKey{ 175 Curve: crypto.S256(), 176 X: x, 177 Y: y, 178 }, 179 } 180 } 181 182 return &_ECDSAPublicKey{ 183 &ecdsa.PublicKey{ 184 Curve: sk.keyData.Curve, 185 X: sk.keyData.X, 186 Y: sk.keyData.Y, 187 }, 188 } 189 } 190 191 func _ECDSAPrivateKeyFromPem(bytes []byte, passphrase string) (*_ECDSAPrivateKey, error) { 192 block, _ := pem.Decode(bytes) 193 if block == nil { 194 return nil, fmt.Errorf("failed to decode PEM block containing private key") 195 } 196 197 if block.Type != "EC PRIVATE KEY" { 198 return nil, fmt.Errorf("unsupported PEM block type: %s", block.Type) 199 } 200 //nolint 201 if x509.IsEncryptedPEMBlock(block) { 202 der, err := x509.DecryptPEMBlock(block, []byte(passphrase)) 203 if err != nil { 204 return nil, err 205 } 206 block.Bytes = der 207 } 208 209 key, err := _ECDSAPrivateKeyFromBytes(block.Bytes) 210 if err != nil { 211 return nil, err 212 } 213 return key, nil 214 } 215 216 func _ECDSAPrivateKeyReadPem(source io.Reader, passphrase string) (*_ECDSAPrivateKey, error) { 217 pemFileBytes, err := io.ReadAll(source) 218 if err != nil { 219 return &_ECDSAPrivateKey{}, err 220 } 221 222 return _ECDSAPrivateKeyFromPem(pemFileBytes, passphrase) 223 } 224 225 func (sk _ECDSAPrivateKey) _Sign(message []byte) []byte { 226 hash := crypto.Keccak256Hash(message) 227 sig, err := crypto.Sign(hash.Bytes(), sk.keyData) 228 if err != nil { 229 panic(err) 230 } 231 232 // signature returned has a ecdsa recovery byte at the end, 233 // need to remove it for verification to work. 234 return sig[:len(sig)-1] 235 } 236 237 // SupportsDerivation returns true if the _ECDSAPrivateKey supports derivation. 238 func (sk _ECDSAPrivateKey) _SupportsDerivation() bool { 239 return sk.chainCode != nil 240 } 241 242 // Derive a child key compatible with the iOS and Android wallets using a provided wallet/account index. Use index 0 for 243 // the default account. 244 // 245 // This will fail if the key does not support derivation which can be checked by calling SupportsDerivation() 246 func (sk _ECDSAPrivateKey) _Derive(index uint32) (*_ECDSAPrivateKey, error) { 247 if !sk._SupportsDerivation() { 248 return nil, _NewErrBadKeyf("child key cannot be derived from this key") 249 } 250 251 derivedKeyBytes, chainCode, err := _DeriveECDSAChildKey(sk._BytesRaw(), sk.chainCode, index) 252 if err != nil { 253 return nil, err 254 } 255 256 derivedKey, err := _ECDSAPrivateKeyFromBytes(derivedKeyBytes) 257 if err != nil { 258 return nil, err 259 } 260 261 derivedKey.chainCode = chainCode 262 263 return derivedKey, nil 264 } 265 266 func (sk _ECDSAPrivateKey) _BytesRaw() []byte { 267 privateKey := make([]byte, 32) 268 temp := sk.keyData.D.Bytes() 269 copy(privateKey[32-len(temp):], temp) 270 271 return privateKey 272 } 273 274 func (sk _ECDSAPrivateKey) _BytesDer() []byte { 275 type ECPrivateKey struct { 276 Version int 277 PrivateKey []byte 278 NamedCurveOID asn1.ObjectIdentifier `asn1:"optional,explicit,tag:0"` 279 PublicKey asn1.BitString `asn1:"optional,explicit,tag:1"` 280 } 281 282 secp256k1OID := asn1.ObjectIdentifier{1, 3, 132, 0, 10} 283 284 ecPrivateKey := ECPrivateKey{ 285 Version: 1, // EC private keys have a version of 1 286 PrivateKey: sk._BytesRaw(), 287 NamedCurveOID: secp256k1OID, 288 PublicKey: asn1.BitString{Bytes: sk._PublicKey()._BytesRaw()}, 289 } 290 291 derBytes, err := asn1.Marshal(ecPrivateKey) 292 if err != nil { 293 return nil 294 } 295 296 return derBytes 297 } 298 299 func (sk _ECDSAPrivateKey) String() string { 300 return sk._StringRaw() 301 } 302 303 func (sk _ECDSAPrivateKey) _StringDer() string { 304 return fmt.Sprint(hex.EncodeToString(sk._BytesDer())) 305 } 306 307 func (sk _ECDSAPrivateKey) _StringRaw() string { 308 return fmt.Sprint(hex.EncodeToString(sk._BytesRaw())) 309 } 310 311 func (sk _ECDSAPrivateKey) _ToProtoKey() *services.Key { 312 return sk._PublicKey()._ToProtoKey() 313 } 314 315 // _SignTransaction signes the transaction and adds the signature to the transaction 316 func (sk _ECDSAPrivateKey) _SignTransaction(tx *Transaction) ([]byte, error) { 317 tx._RequireOneNodeAccountID() 318 319 if tx.signedTransactions._Length() == 0 { 320 return make([]byte, 0), errTransactionRequiresSingleNodeAccountID 321 } 322 323 signature := sk._Sign(tx.signedTransactions._Get(0).(*services.SignedTransaction).GetBodyBytes()) 324 325 publicKey := sk._PublicKey() 326 if publicKey == nil { 327 return []byte{}, errors.New("public key is nil") 328 } 329 330 wrappedPublicKey := PublicKey{ 331 ecdsaPublicKey: publicKey, 332 } 333 334 if tx._KeyAlreadySigned(wrappedPublicKey) { 335 return []byte{}, nil 336 } 337 338 tx.transactions = _NewLockableSlice() 339 tx.publicKeys = append(tx.publicKeys, wrappedPublicKey) 340 tx.transactionSigners = append(tx.transactionSigners, nil) 341 tx.transactionIDs.locked = true 342 343 for index := 0; index < tx.signedTransactions._Length(); index++ { 344 temp := tx.signedTransactions._Get(index).(*services.SignedTransaction) 345 346 temp.SigMap.SigPair = append( 347 temp.SigMap.SigPair, 348 publicKey._ToSignaturePairProtobuf(signature), 349 ) 350 tx.signedTransactions._Set(index, temp) 351 } 352 353 return signature, nil 354 }