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 }