Generate a New Ethereum Wallet Using Go

Β·

Creating a new Ethereum wallet programmatically is a foundational skill for blockchain developers, especially those working with Go (Golang). In this guide, you’ll learn how to generate a secure Ethereum wallet using the go-ethereum library. We'll walk through generating a private key, deriving the public key, and computing the Ethereum address β€” all using clean, efficient Go code.

Whether you're building decentralized applications (dApps), automating blockchain interactions, or exploring cryptographic fundamentals, understanding wallet generation is essential. This tutorial focuses on practical implementation while maintaining security best practices.


Step 1: Generate a Private Key

The foundation of any Ethereum wallet is the private key β€” a 256-bit number that must remain secret. With Go and the go-ethereum library, generating a cryptographically secure private key is straightforward.

Start by importing the github.com/ethereum/go-ethereum/crypto package, which provides tools for Ethereum-specific cryptography:

privateKey, err := crypto.GenerateKey()
if err != nil {
    log.Fatal(err)
}

This generates a valid ECDSA private key using the secp256k1 curve, the standard for Ethereum. If an error occurs during generation (e.g., insufficient entropy), it will be logged.

πŸ‘‰ Discover how blockchain developers use secure key management in production environments.


Step 2: Convert Private Key to Bytes and Hex

Once generated, convert the private key into a byte slice for encoding. Use the crypto.FromECDSA() method:

privateKeyBytes := crypto.FromECDSA(privateKey)

To make it human-readable and suitable for storage or display (in secure contexts), encode it as a hexadecimal string using hexutil.Encode:

fmt.Println(hexutil.Encode(privateKeyBytes)[2:]) 
// Example output: fad9c8855b740a0b7ed4c221dbad0f33a83a49cad6b3fe8d5817ac83d38b6a19
πŸ” Security Note: The private key is your wallet's master password. Never expose it in logs, client-side code, or public repositories.

This hexadecimal string represents your Ethereum private key, used to sign transactions and prove ownership of funds.


Step 3: Derive the Public Key

The public key is derived mathematically from the private key. While the private key must stay secret, the public key can be shared β€” though it’s rarely needed directly, as we usually work with the Ethereum address.

Use the .Public() method on the private key and assert its type as *ecdsa.PublicKey:

publicKey := privateKey.Public()
publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
if !ok {
    log.Fatal("cannot assert type: publicKey is not of type *ecdsa.PublicKey")
}

Then convert it to bytes:

publicKeyBytes := crypto.FromECDSAPub(publicKeyECDSA)

Encode it in hex (removing the 0x prefix and the leading 04, which indicates an uncompressed point):

fmt.Println(hexutil.Encode(publicKeyBytes)[4:])
// Example output: 9a7df67f79246283fdc93af76d4f8cdd62c4886e8cd870944e817dd0b97934fdd7719d0810951e03418205868a5c1b40b192451367f28e0088dd75e15de40c05

Step 4: Generate the Ethereum Address

The Ethereum address is what you share to receive funds. It's derived from the last 20 bytes of the Keccak-256 hash of the public key.

The easiest way is using crypto.PubkeyToAddress:

address := crypto.PubkeyToAddress(*publicKeyECDSA).Hex()
fmt.Println(address) 
// Output: 0x96216849c49358B10257cb55b28eA603c874b05E

Alternatively, compute it manually using Keccak-256 (note: not standard SHA-3):

hash := sha3.NewLegacyKeccak256()
hash.Write(publicKeyBytes[1:]) // Skip the leading 0x04
fmt.Println(hexutil.Encode(hash.Sum(nil)[12:])) 
// Output: 0x96216849c49358b10257cb55b28ea603c874b05e

Both methods yield the same result β€” your public Ethereum address.

πŸ‘‰ Learn how developers securely manage keys in real-world blockchain applications.


Complete Working Code Example

Here's the full Go program that generates a new Ethereum wallet:

package main

import (
    "crypto/ecdsa"
    "fmt"
    "log"
    "github.com/ethereum/go-ethereum/common/hexutil"
    "github.com/ethereum/go-ethereum/crypto"
    "golang.org/x/crypto/sha3"
)

func main() {
    // Step 1: Generate private key
    privateKey, err := crypto.GenerateKey()
    if err != nil {
        log.Fatal(err)
    }

    // Step 2: Encode private key to hex
    privateKeyBytes := crypto.FromECDSA(privateKey)
    fmt.Println("Private Key:", hexutil.Encode(privateKeyBytes)[2:])

    // Step 3: Derive and encode public key
    publicKey := privateKey.Public()
    publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
    if !ok {
        log.Fatal("Invalid public key type")
    }
    publicKeyBytes := crypto.FromECDSAPub(publicKeyECDSA)
    fmt.Println("Public Key:", hexutil.Encode(publicKeyBytes)[4:])

    // Step 4: Generate Ethereum address
    address := crypto.PubkeyToAddress(*publicKeyECDSA).Hex()
    fmt.Println("Address:", address)

    // Optional: Manual address derivation via Keccak-256
    hash := sha3.NewLegacyKeccak256()
    hash.Write(publicKeyBytes[1:])
    manualAddress := hexutil.Encode(hash.Sum(nil)[12:])
    fmt.Println("Manual Address:", "0x"+manualAddress)
}

Run this with go run wallet_generate.go to generate a new wallet each time.


Frequently Asked Questions (FAQ)

Q: Is it safe to generate wallets using Go in production?

Yes β€” as long as you follow security best practices. Ensure your environment has sufficient entropy, avoid logging sensitive data, and never store private keys in plaintext. For production systems, consider hardware security modules (HSMs) or secure key vaults.

Q: Can I recover funds if I lose my private key?

No. The private key is irreplaceable. Without it, access to associated funds is permanently lost. Always back up keys securely using encrypted storage or mnemonic phrases (BIP39), which this guide does not cover but is recommended for wallet recovery.

Q: Why do we remove '0x' and '04' when encoding keys?

The 0x is a hexadecimal prefix not needed in raw representations. The 04 indicates an uncompressed EC point β€” always present in Ethereum public keys β€” so it's often stripped for brevity in custom formats, though it's required during cryptographic operations.

Q: What is the difference between Keccak-256 and SHA-3?

Ethereum uses Keccak-256, a variant of SHA-3 used before final standardization. They are similar but not identical. Always use sha3.NewLegacyKeccak256() from golang.org/x/crypto/sha3 for Ethereum compatibility.

Q: Can I generate multiple addresses from one private key?

No β€” one private key generates exactly one public key and one Ethereum address. However, hierarchical deterministic (HD) wallets use a seed phrase to derive multiple key pairs securely.


Core Keywords


By mastering wallet generation in Go, you're laying the groundwork for advanced blockchain interactions β€” from signing transactions to building custom wallets and dApp backends. Always prioritize security and test thoroughly in sandboxed environments before deploying to mainnet.

πŸ‘‰ Explore advanced tools and APIs used by professional blockchain developers today.