package main import ( "crypto/ecdsa" "fmt" "log" "golang.org/x/crypto/sha3" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" ) const message = "Hello Ethereum world" func main() { privateKey, address, err := generateAddressAndPrivateKey() if err != nil { log.Fatalf("failed to generate address and private key: %v", err) } signature, err := signMessage(privateKey, message) if err != nil { log.Fatalf("failed to sign message: %v", err) } err = verifySignature(address, signature, message) if err != nil { log.Fatalf("failed to verify signature: %v", err) } fmt.Printf("Successfully signed and verified message '%s' with Ethereum address %s\n", message, address) } func signMessage(privateKey *ecdsa.PrivateKey, message string) (string, error) { messageHash := accounts.TextHash([]byte(message)) signature, err := crypto.Sign(messageHash, privateKey) if err != nil { return "", err } signature[crypto.RecoveryIDOffset] += 27 return hexutil.Encode(signature), nil } func verifySignature(fromAddress, signatureHex, message string) error { signature, err := hexutil.Decode(signatureHex) if err != nil { return err } signature[crypto.RecoveryIDOffset] -= 27 // Transform yellow paper V from 27/28 to 0/1 messageHash := accounts.TextHash([]byte(message)) pubKey, err := crypto.SigToPub(messageHash, signature) if err != nil { return err } if common.HexToAddress(fromAddress) != crypto.PubkeyToAddress(*pubKey) { return fmt.Errorf("failed to verify signature") } return nil } func generateAddressAndPrivateKey() (*ecdsa.PrivateKey, string, error) { privateKey, err := crypto.GenerateKey() if err != nil { return nil, "", err } publicKey := privateKey.Public().(*ecdsa.PublicKey) publicKeyBytes := crypto.FromECDSAPub(publicKey) hash := sha3.NewLegacyKeccak256() hash.Write(publicKeyBytes[1:]) address := hexutil.Encode(hash.Sum(nil)[12:]) return privateKey, address, nil }