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  }