github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/x/auth/ibc-tx/internal/ethsecp256k1/ethsecp256k1.go (about)

     1  package ethsecp256k1
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/ecdsa"
     6  	"crypto/subtle"
     7  	"fmt"
     8  
     9  	"github.com/ethereum/go-ethereum/crypto"
    10  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec"
    11  	cryptotypes "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/crypto/types"
    12  	sdkerrors "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/errors"
    13  
    14  	tmcrypto "github.com/fibonacci-chain/fbc/libs/tendermint/crypto"
    15  )
    16  
    17  const (
    18  	// PrivKeySize defines the size of the PrivKey bytes
    19  	PrivKeySize = 32
    20  	// PubKeySize defines the size of the PubKey bytes
    21  	PubKeySize = 33
    22  	// KeyType is the string constant for the Secp256k1 algorithm
    23  	KeyType = "eth_secp256k1"
    24  )
    25  
    26  // Amino encoding names
    27  const (
    28  	// PrivKeyName defines the amino encoding name for the EthSecp256k1 private key
    29  	PrivKeyName = "ethermint/PrivKeyEthSecp256k1"
    30  	// PubKeyName defines the amino encoding name for the EthSecp256k1 public key
    31  	PubKeyName = "ethermint/PubKeyEthSecp256k1"
    32  )
    33  
    34  // ----------------------------------------------------------------------------
    35  // secp256k1 Private Key
    36  
    37  var (
    38  	_ cryptotypes.PrivKey  = &PrivKey{}
    39  	_ codec.AminoMarshaler = &PrivKey{}
    40  )
    41  
    42  // GenerateKey generates a new random private key. It returns an error upon
    43  // failure.
    44  func GenerateKey() (*PrivKey, error) {
    45  	priv, err := crypto.GenerateKey()
    46  	if err != nil {
    47  		return nil, err
    48  	}
    49  
    50  	return &PrivKey{
    51  		Key: crypto.FromECDSA(priv),
    52  	}, nil
    53  }
    54  
    55  // Bytes returns the byte representation of the ECDSA Private Key.
    56  func (privKey PrivKey) Bytes() []byte {
    57  	bz := make([]byte, len(privKey.Key))
    58  	copy(bz, privKey.Key)
    59  
    60  	return bz
    61  }
    62  
    63  // PubKey returns the ECDSA private key's public key. If the privkey is not valid
    64  // it returns a nil value.
    65  func (privKey PrivKey) PubKey() cryptotypes.PubKey {
    66  	ecdsaPrivKey, err := privKey.ToECDSA()
    67  	if err != nil {
    68  		return nil
    69  	}
    70  
    71  	return &PubKey{
    72  		Key: crypto.CompressPubkey(&ecdsaPrivKey.PublicKey),
    73  	}
    74  }
    75  
    76  // Equals returns true if two ECDSA private keys are equal and false otherwise.
    77  func (privKey PrivKey) Equals(other cryptotypes.LedgerPrivKey) bool {
    78  	return privKey.Type() == other.Type() && subtle.ConstantTimeCompare(privKey.Bytes(), other.Bytes()) == 1
    79  }
    80  
    81  // Type returns eth_secp256k1
    82  func (privKey PrivKey) Type() string {
    83  	return KeyType
    84  }
    85  
    86  // MarshalAmino overrides Amino binary marshaling.
    87  func (privKey PrivKey) MarshalAmino() ([]byte, error) {
    88  	return privKey.Key, nil
    89  }
    90  
    91  // UnmarshalAmino overrides Amino binary marshaling.
    92  func (privKey *PrivKey) UnmarshalAmino(bz []byte) error {
    93  	if len(bz) != PrivKeySize {
    94  		return fmt.Errorf("invalid privkey size, expected %d got %d", PrivKeySize, len(bz))
    95  	}
    96  	privKey.Key = bz
    97  
    98  	return nil
    99  }
   100  
   101  // MarshalAminoJSON overrides Amino JSON marshaling.
   102  func (privKey PrivKey) MarshalAminoJSON() ([]byte, error) {
   103  	// When we marshal to Amino JSON, we don't marshal the "key" field itself,
   104  	// just its contents (i.e. the key bytes).
   105  	return privKey.MarshalAmino()
   106  }
   107  
   108  // UnmarshalAminoJSON overrides Amino JSON marshaling.
   109  func (privKey *PrivKey) UnmarshalAminoJSON(bz []byte) error {
   110  	return privKey.UnmarshalAmino(bz)
   111  }
   112  
   113  // Sign creates a recoverable ECDSA signature on the secp256k1 curve over the
   114  // provided hash of the message. The produced signature is 65 bytes
   115  // where the last byte contains the recovery ID.
   116  func (privKey PrivKey) Sign(digestBz []byte) ([]byte, error) {
   117  	// TODO: remove
   118  	if len(digestBz) != crypto.DigestLength {
   119  		digestBz = crypto.Keccak256Hash(digestBz).Bytes()
   120  	}
   121  
   122  	key, err := privKey.ToECDSA()
   123  	if err != nil {
   124  		return nil, err
   125  	}
   126  
   127  	return crypto.Sign(digestBz, key)
   128  }
   129  
   130  // ToECDSA returns the ECDSA private key as a reference to ecdsa.PrivateKey type.
   131  func (privKey PrivKey) ToECDSA() (*ecdsa.PrivateKey, error) {
   132  	return crypto.ToECDSA(privKey.Bytes())
   133  }
   134  
   135  // ----------------------------------------------------------------------------
   136  // secp256k1 Public Key
   137  
   138  var (
   139  	_ cryptotypes.PubKey   = &PubKey{}
   140  	_ codec.AminoMarshaler = &PubKey{}
   141  )
   142  
   143  // Address returns the address of the ECDSA public key.
   144  // The function will return an empty address if the public key is invalid.
   145  func (pubKey PubKey) Address() tmcrypto.Address {
   146  	pubk, err := crypto.DecompressPubkey(pubKey.Key)
   147  	if err != nil {
   148  		return nil
   149  	}
   150  
   151  	return tmcrypto.Address(crypto.PubkeyToAddress(*pubk).Bytes())
   152  }
   153  
   154  // Bytes returns the raw bytes of the ECDSA public key.
   155  func (pubKey PubKey) Bytes() []byte {
   156  	bz := make([]byte, len(pubKey.Key))
   157  	copy(bz, pubKey.Key)
   158  
   159  	return bz
   160  }
   161  
   162  // String implements the fmt.Stringer interface.
   163  func (pubKey PubKey) String() string {
   164  	return fmt.Sprintf("EthPubKeySecp256k1{%X}", pubKey.Key)
   165  }
   166  
   167  // Type returns eth_secp256k1
   168  func (pubKey PubKey) Type() string {
   169  	return KeyType
   170  }
   171  
   172  // Equals returns true if the pubkey type is the same and their bytes are deeply equal.
   173  func (pubKey PubKey) Equals(other cryptotypes.PubKey) bool {
   174  	return pubKey.Type() == other.Type() && bytes.Equal(pubKey.Bytes(), other.Bytes())
   175  }
   176  
   177  // MarshalAmino overrides Amino binary marshaling.
   178  func (pubKey PubKey) MarshalAmino() ([]byte, error) {
   179  	return pubKey.Key, nil
   180  }
   181  
   182  // UnmarshalAmino overrides Amino binary marshaling.
   183  func (pubKey *PubKey) UnmarshalAmino(bz []byte) error {
   184  	if len(bz) != PubKeySize {
   185  		return sdkerrors.Wrapf(sdkerrors.ErrInvalidPubKey, "invalid pubkey size, expected %d, got %d", PubKeySize, len(bz))
   186  	}
   187  	pubKey.Key = bz
   188  
   189  	return nil
   190  }
   191  
   192  // MarshalAminoJSON overrides Amino JSON marshaling.
   193  func (pubKey PubKey) MarshalAminoJSON() ([]byte, error) {
   194  	// When we marshal to Amino JSON, we don't marshal the "key" field itself,
   195  	// just its contents (i.e. the key bytes).
   196  	return pubKey.MarshalAmino()
   197  }
   198  
   199  // UnmarshalAminoJSON overrides Amino JSON marshaling.
   200  func (pubKey *PubKey) UnmarshalAminoJSON(bz []byte) error {
   201  	return pubKey.UnmarshalAmino(bz)
   202  }
   203  
   204  // VerifySignature verifies that the ECDSA public key created a given signature over
   205  // the provided message. It will calculate the Keccak256 hash of the message
   206  // prior to verification.
   207  //
   208  // CONTRACT: The signature should be in [R || S] format.
   209  func (pubKey PubKey) VerifySignature(msg, sig []byte) bool {
   210  	if len(sig) == crypto.SignatureLength {
   211  		// remove recovery ID (V) if contained in the signature
   212  		sig = sig[:len(sig)-1]
   213  	}
   214  
   215  	// the signature needs to be in [R || S] format when provided to VerifySignature
   216  	return crypto.VerifySignature(pubKey.Key, crypto.Keccak256Hash(msg).Bytes(), sig)
   217  }