github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/app/crypto/ethsecp256k1/ethsecp256k1.go (about)

     1  package ethsecp256k1
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/ecdsa"
     6  
     7  	"github.com/ethereum/go-ethereum/common"
     8  	ethcrypto "github.com/ethereum/go-ethereum/crypto"
     9  	"github.com/ethereum/go-ethereum/crypto/secp256k1"
    10  
    11  	tmcrypto "github.com/fibonacci-chain/fbc/libs/tendermint/crypto"
    12  )
    13  
    14  const (
    15  	// PrivKeySize defines the size of the PrivKey bytes
    16  	PrivKeySize = 32
    17  	// KeyType is the string constant for the EthSecp256k1 algorithm
    18  	KeyType = "eth_secp256k1"
    19  )
    20  
    21  // Amino encoding names
    22  const (
    23  	// PrivKeyName defines the amino encoding name for the EthSecp256k1 private key
    24  	PrivKeyName = "ethermint/PrivKeyEthSecp256k1"
    25  	// PubKeyName defines the amino encoding name for the EthSecp256k1 public key
    26  	PubKeyName = "ethermint/PubKeyEthSecp256k1"
    27  )
    28  
    29  // ----------------------------------------------------------------------------
    30  // secp256k1 Private Key
    31  
    32  var _ tmcrypto.PrivKey = PrivKey{}
    33  
    34  // PrivKey defines a type alias for an ecdsa.PrivateKey that implements
    35  // Tendermint's PrivateKey interface.
    36  type PrivKey []byte
    37  
    38  // GenerateKey generates a new random private key. It returns an error upon
    39  // failure.
    40  func GenerateKey() (PrivKey, error) {
    41  	priv, err := ethcrypto.GenerateKey()
    42  	if err != nil {
    43  		return PrivKey{}, err
    44  	}
    45  
    46  	return PrivKey(ethcrypto.FromECDSA(priv)), nil
    47  }
    48  
    49  // GenerateAddress generates an Ethereum address.
    50  func GenerateAddress() common.Address {
    51  	privk, _ := GenerateKey()
    52  	return ethcrypto.PubkeyToAddress(privk.ToECDSA().PublicKey)
    53  }
    54  
    55  // PubKey returns the ECDSA private key's public key.
    56  func (privkey PrivKey) PubKey() tmcrypto.PubKey {
    57  	ecdsaPKey := privkey.ToECDSA()
    58  	return PubKey(ethcrypto.CompressPubkey(&ecdsaPKey.PublicKey))
    59  }
    60  
    61  // Bytes returns the raw ECDSA private key bytes.
    62  func (privkey PrivKey) Bytes() []byte {
    63  	return CryptoCodec.MustMarshalBinaryBare(privkey)
    64  }
    65  
    66  // Sign creates a recoverable ECDSA signature on the secp256k1 curve over the
    67  // Keccak256 hash of the provided message. The produced signature is 65 bytes
    68  // where the last byte contains the recovery ID.
    69  func (privkey PrivKey) Sign(msg []byte) ([]byte, error) {
    70  	return ethcrypto.Sign(ethcrypto.Keccak256Hash(msg).Bytes(), privkey.ToECDSA())
    71  }
    72  
    73  // Equals returns true if two ECDSA private keys are equal and false otherwise.
    74  func (privkey PrivKey) Equals(other tmcrypto.PrivKey) bool {
    75  	if other, ok := other.(PrivKey); ok {
    76  		return bytes.Equal(privkey.Bytes(), other.Bytes())
    77  	}
    78  
    79  	return false
    80  }
    81  
    82  // ToECDSA returns the ECDSA private key as a reference to ecdsa.PrivateKey type.
    83  // The function will panic if the private key is invalid.
    84  func (privkey PrivKey) ToECDSA() *ecdsa.PrivateKey {
    85  	key, err := ethcrypto.ToECDSA(privkey)
    86  	if err != nil {
    87  		panic(err)
    88  	}
    89  	return key
    90  }
    91  
    92  // ----------------------------------------------------------------------------
    93  // secp256k1 Public Key
    94  
    95  var _ tmcrypto.PubKey = (*PubKey)(nil)
    96  
    97  // PubKey defines a type alias for an ecdsa.PublicKey that implements Tendermint's PubKey
    98  // interface. It represents the 33-byte compressed public key format.
    99  type PubKey []byte
   100  
   101  // Address returns the address of the ECDSA public key.
   102  // The function will panic if the public key is invalid.
   103  func (key PubKey) Address() tmcrypto.Address {
   104  	pubk, err := ethcrypto.DecompressPubkey(key)
   105  	if err != nil {
   106  		panic(err)
   107  	}
   108  
   109  	return tmcrypto.Address(ethcrypto.PubkeyToAddress(*pubk).Bytes())
   110  }
   111  
   112  // Bytes returns the raw bytes of the ECDSA public key.
   113  // The function panics if the key cannot be marshaled to bytes.
   114  func (key PubKey) Bytes() []byte {
   115  	bz, err := CryptoCodec.MarshalBinaryBare(key)
   116  	if err != nil {
   117  		panic(err)
   118  	}
   119  	return bz
   120  }
   121  
   122  // VerifyBytes verifies that the ECDSA public key created a given signature over
   123  // the provided message. It will calculate the Keccak256 hash of the message
   124  // prior to verification.
   125  func (key PubKey) VerifyBytes(msg []byte, sig []byte) bool {
   126  	if len(sig) == 65 {
   127  		// remove recovery ID if contained in the signature
   128  		sig = sig[:len(sig)-1]
   129  	}
   130  
   131  	// the signature needs to be in [R || S] format when provided to VerifySignature
   132  	return secp256k1.VerifySignature(key, ethcrypto.Keccak256Hash(msg).Bytes(), sig)
   133  }
   134  
   135  // Equals returns true if two ECDSA public keys are equal and false otherwise.
   136  func (key PubKey) Equals(other tmcrypto.PubKey) bool {
   137  	if other, ok := other.(PubKey); ok {
   138  		return bytes.Equal(key.Bytes(), other.Bytes())
   139  	}
   140  
   141  	return false
   142  }