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 }