In Ethereum, we use ECC (Elliptic Curve Cryptography) to create a public key and a private key. The private key is kept secure, and then the public key is used to derive the Ethereum address. When we sign for a transaction, we use our private key, and to create a signature, and which is automatically checked against our Ethereum address.
Creating Ethereum Wallets in Go |
Theory
In Ethereum, we use ECC (Elliptic Curve Cryptography) to create a public key and a private key. The private key is kept secure, and then the public key is used to derive the Ethereum address. When we sign for a transaction, we use our private key, and to create a signature, and which is automatically checked against our Ethereum address.
In creating the keys (for our wallet) we generate a 256-bit private key, and then the public key is a point on the secp256k1 ECDSA curve (x,y point). This key is then hashed using Keccak-256 (aka SHA-3), and the lower 160 bits becomes the public Ethereum address :
The private key should be completely random, and there are 2²⁵⁶ different keys that can be generated, so the chance of us matching a private key to a public key is:
1 in 1,550 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 … 000 (75 zeros — 1.55 quattuorvigintillion)package main import ( "crypto/ecdsa" "fmt" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" "golang.org/x/crypto/sha3" ) func main() { privateKey,_ := crypto.GenerateKey() privateKeyBytes := crypto.FromECDSA(privateKey) fmt.Printf("Private key: %s\n",hexutil.Encode(privateKeyBytes)[2:]) publicKey := privateKey.Public() publicKeyECDSA, _ := publicKey.(*ecdsa.PublicKey) publicKeyBytes := crypto.FromECDSAPub(publicKeyECDSA) fmt.Printf("Public key:\t %s\n",hexutil.Encode(publicKeyBytes)[4:]) address := crypto.PubkeyToAddress(*publicKeyECDSA).Hex() fmt.Printf("Public address (from ECDSA): \t%s\n",address) hash := sha3.NewLegacyKeccak256() hash.Write(publicKeyBytes[1:]) fmt.Printf("Public address (Hash of public key):\t%s\n",hexutil.Encode(hash.Sum(nil)[12:])) }
A sample run is defined below. Notice that Bob and Alice get the same values for DH1, DH2 and DH3, and can thus generate the same key:
Private key: 730fd66ddfb35bd861690a5fff6387654c6a130bb7a8b8f8740fe885cf7976ce Public key: c25aeed2481f4682aba6a95e9765c37b6f0fd7006bb84fddc14682351b8fd23336df6467c6b90c4604ef5bc269494af9fc076fe6efff305b9e4491425adc6e23 Public address (from ECDSA): 0x0E3b57a13452cc08826080Ba1C1Af56266a5dAee Public address (Hash of public key): 0x0e3b57a13452cc08826080ba1c1af56266a5daee