Creating an Ethereum wallet programmatically is a fundamental skill for blockchain developers, especially those building decentralized applications (dApps) or tools that interact with the Ethereum network. In this guide, you’ll learn how to generate a new Ethereum wallet using the Go programming language and the popular go-ethereum library. We’ll walk through generating private keys, deriving public keys, and computing Ethereum addresses—all while maintaining security best practices.
Whether you're building a wallet service, integrating crypto functionality into your backend, or just exploring blockchain development, understanding wallet generation is essential.
Understanding Ethereum Wallets in Go
An Ethereum wallet is essentially a pair of cryptographic keys: a private key and its corresponding public key, from which an Ethereum address is derived. The private key must remain secret, as it grants full control over the associated funds. The public key and address can be safely shared for receiving transactions.
To generate these components in Go, we use the go-ethereum libraries:
github.com/ethereum/go-ethereum/crypto– for key generation and hashing.crypto/ecdsa– for handling ECDSA cryptographic operations.golang.org/x/crypto/sha3– for Keccak-256 hashing.
👉 Learn how to securely manage cryptographic keys in production environments.
Step 1: Generate a Private Key
The foundation of any wallet is the private key, a 256-bit number used to sign transactions. We use the crypto.GenerateKey() function from the go-ethereum library to create a cryptographically secure private key.
privateKey, err := crypto.GenerateKey()
if err != nil {
log.Fatal(err)
}This method leverages Go’s built-in cryptographic randomness to ensure unpredictability and security.
Next, convert the private key into a byte slice for encoding:
privateKeyBytes := crypto.FromECDSA(privateKey)Now encode it as a hexadecimal string (without the 0x prefix):
fmt.Println(hexutil.Encode(privateKeyBytes)[2:])
// Output: fad9c8855b740a0b7ed4c221dbad0f33a83a49cad6b3fe8d5817ac83d38b6a19🔐 Important: Never expose this private key in logs, frontend code, or public repositories. It controls access to all associated assets on the blockchain.
Step 2: Derive the Public Key
From the private key, we derive the public key using elliptic curve cryptography (secp256k1). The Go Ethereum library provides a direct method:
publicKey := privateKey.Public()Since this returns an interface, we need to type-assert it to *ecdsa.PublicKey:
publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
if !ok {
log.Fatal("cannot assert type: publicKey is not of type *ecdsa.PublicKey")
}Convert the public key to bytes:
publicKeyBytes := crypto.FromECDSAPub(publicKeyECDSA)Then encode it in hexadecimal format. Note that uncompressed public keys start with 0x04, which we typically omit when displaying:
fmt.Println(hexutil.Encode(publicKeyBytes)[4:])
// Output: 9a7df67f79246283fdc93af76d4f8cdd62c4886e8cd870944e817dd0b97934fdd7719d0810951e03418205868a5c1b40b192451367f28e0088dd75e15de40c05Step 3: Generate the Ethereum Address
The Ethereum address is what users share to receive funds. It's derived by taking the last 20 bytes of the Keccak-256 hash of the public key (excluding the 0x04 prefix).
The easiest way using go-ethereum:
address := crypto.PubkeyToAddress(*publicKeyECDSA).Hex()
fmt.Println(address)
// Output: 0x96216849c49358B10257cb55b28eA603c874b05EAlternatively, compute it manually using Keccak-256:
hash := sha3.NewLegacyKeccak256()
hash.Write(publicKeyBytes[1:]) // Skip the 0x04 prefix
fmt.Println(hexutil.Encode(hash.Sum(nil)[12:]))
// Output: 0x96216849c49358b10257cb55b28ea603c874b05eBoth methods yield the same result—the standard Ethereum address format.
👉 Discover best practices for secure wallet implementation in dApps.
Core Keywords for SEO
To align with search intent and improve visibility, here are the core keywords naturally integrated throughout this article:
- Ethereum wallet generation
- Go Ethereum crypto
- Generate private key Go
- Derive Ethereum address
- Keccak-256 hash Go
- ECDSA public key Go
- Blockchain wallet development
- Secure key management
These terms reflect common queries from developers seeking hands-on guidance for implementing Ethereum wallets in Go.
Frequently Asked Questions
How is an Ethereum address derived from a public key?
An Ethereum address is created by applying the Keccak-256 hash function to the raw bytes of the uncompressed public key (excluding the 0x04 prefix), then taking the last 20 bytes of the result and prefixing them with 0x.
Is it safe to generate wallets offline using Go?
Yes, generating wallets offline in Go is highly secure—especially when using well-audited libraries like go-ethereum. Since no network calls are involved during key generation, there's minimal risk of exposure if proper precautions (like avoiding logging keys) are followed.
Can I recover funds if I lose my private key?
No. Unlike traditional accounts, Ethereum wallets do not have a recovery mechanism. If you lose your private key or seed phrase, access to funds is permanently lost. Always back up keys securely using encrypted storage or hardware solutions.
Why do we remove the first two characters (0x04) from the public key?
The 0x04 prefix indicates an uncompressed ECDSA public key. While necessary during cryptographic operations, it's omitted during address derivation because only the raw coordinate data is hashed.
What’s the difference between SHA3 and Keccak-256?
Although often used interchangeably, Keccak-256 is the original hash function developed for SHA-3. The version used in Ethereum (sha3.NewLegacyKeccak256) differs slightly from the final NIST-standardized SHA-3. Using the correct variant is critical for compatibility.
Can I use this code in production?
While this example demonstrates correct principles, production systems should include additional safeguards: secure key storage (e.g., HSMs), input validation, error handling, and audit-ready logging practices.
Complete Working Code Example
Below is 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)
}
// Convert private key to bytes and print hex
privateKeyBytes := crypto.FromECDSA(privateKey)
fmt.Println("Private Key:", hexutil.Encode(privateKeyBytes)[2:])
// Step 2: Derive public key
publicKey := privateKey.Public()
publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
if !ok {
log.Fatal("cannot assert type: publicKey is not of type *ecdsa.PublicKey")
}
publicKeyBytes := crypto.FromECDSAPub(publicKeyECDSA)
fmt.Println("Public Key:", hexutil.Encode(publicKeyBytes)[4:])
// Step 3: Generate Ethereum address
address := crypto.PubkeyToAddress(*publicKeyECDSA).Hex()
fmt.Println("Address:", address)
// 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 after installing dependencies:
go get -u github.com/ethereum/go-ethereum/crypto golang.org/x/crypto/sha3By mastering Ethereum wallet creation in Go, you gain powerful tools for building secure, scalable blockchain applications. Whether you're working on infrastructure, exchanges, or dApps, proper cryptographic handling is non-negotiable.
👉 Explore advanced blockchain development techniques and enhance your project’s security posture.