Ethereum Public Key, Private Key, and Address Conversion Basics

·

Understanding the cryptographic foundations of Ethereum is essential for developers, security analysts, and blockchain enthusiasts. At the heart of Ethereum's security model lies elliptic curve cryptography (ECC), specifically the secp256k1 curve. This guide dives into how private keys, public keys, and wallet addresses are generated and interconverted in Ethereum, using practical code examples and clear explanations.

Whether you're building decentralized applications (dApps), managing digital assets, or exploring blockchain internals, mastering key conversion processes enhances both your technical proficiency and security awareness.

Core Concepts: Keys and Addresses in Ethereum

In Ethereum:

These components form the foundation of identity and transaction signing on the Ethereum network.

Generating a Private Key

The first step in creating an Ethereum account is generating a secure private key. Using Go's go-ethereum library, this process is straightforward:

key, err := crypto.GenerateKey()
if err != nil {
    t.Fatalf("failed to generate key: %s", err)
}
fmt.Println("Private key (no 0x):", hex.EncodeToString(crypto.FromECDSA(key)))

This outputs a 64-character hexadecimal string representing 32 bytes — your private key. For example:

b1fb9a42d8478cf19bbc1cb4e75625ced1728c8de8691845f546b2ad84a7d379

👉 Learn how cryptographic keys secure your digital assets

Storing the Private Key Securely

Once generated, it's crucial to store the private key securely. You can save it to a file using:

if err := crypto.SaveECDSA("privatekey", key); err != nil {
    log.Error(fmt.Sprintf("Failed to persist node key: %v", err))
}

This creates a file named privatekey containing the raw private key data. Always protect such files with proper access controls and encryption — never expose them publicly.

Deriving the Public Key

From the private key, the corresponding public key can be computed:

fmt.Println("Public key (no 0x):", hex.EncodeToString(crypto.FromECDSAPub(&key.PublicKey)))

Output example:

0425b775a01b5df335cd71170f6a16d8b43704e68b8eb87a8e6ebfd3deafbfc1151d76bbe078002ffb7caaca06441b1c3976c3ca3b1e1fda9cf0f4591d799758e4

Note that this starts with 0x04, indicating an uncompressed public key. The full key is 65 bytes long (130 hex characters).

Compressing the Public Key

To reduce storage and transmission size, Ethereum supports compressed public keys (33 bytes):

compressed := CompressPubkey(key)
// Later, decompress when needed
decompressedKey, _ := DecompressPubkey(compressed)

Compression retains security while improving efficiency — especially useful in bandwidth-constrained environments.

Converting Keys to Addresses

An Ethereum address is not the public key itself but a derived value:

address := crypto.PubkeyToAddress(key.PublicKey).String()
fmt.Println("Address:", address)

Output:

0x703c4b2bD70c169f5717101CaeE543299Fc946C7

This address is created by:

  1. Hashing the public key with Keccak-256.
  2. Taking the rightmost 20 bytes (40 hex characters).
  3. Adding the 0x prefix.

Creating an Address from a Private Key String

You can also reconstruct a key pair from an existing private key string:

acc1Key, _ := crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
address1 := crypto.PubkeyToAddress(acc1Key.PublicKey)
fmt.Println("Address:", address1.String())

This allows importing existing accounts programmatically.

Working with Raw Bytes: Addresses and Hashes

Sometimes you need to work directly with byte arrays:

// Convert bytes to address
addr3 := common.BytesToAddress([]byte("ethereum"))
fmt.Println("Address from bytes:", addr3.String())

// Convert bytes to hash
hash1 := common.BytesToHash([]byte("topic1"))
fmt.Println("Hash from bytes:", hash1.String())

While these aren't typical for user-facing addresses, they're useful in smart contract development and event logging.

Recovering Public Keys from Signatures

One of Ethereum’s powerful features is the ability to verify identity through message signing. Given a message digest and signature, you can recover the signer’s public key:

msg := crypto.Keccak256([]byte("foo"))
sig, _ := crypto.Sign(msg, key1)

// Method 1: Using Ecrecover
recoveredPub, _ := crypto.Ecrecover(msg, sig)
pubKey, _ := crypto.UnmarshalPubkey(recoveredPub)
recoveredAddr := crypto.PubkeyToAddress(*pubKey)

// Method 2: Direct SigToPub
recoveredPub2, _ := crypto.SigToPub(msg, sig)
recoveredAddr2 := crypto.PubkeyToAddress(*recoveredPub2)

Both methods should yield the same address as the original:

addrtest         0x970E8128AB834E8EAC17Ab8E3812F010678CF791
recoveredAddr    0x970E8128AB834E8EAC17Ab8E3812F010678CF791
recoveredAddr2   0x970E8128AB834E8EAC17Ab8E3812F010678CF791

This mechanism underpins meta-transactions, wallet recovery, and off-chain authentication.

👉 Discover how digital signatures ensure trustless verification

Frequently Asked Questions

What is the length of an Ethereum private key?

An Ethereum private key is exactly 32 bytes (256 bits), represented as a 64-character hexadecimal string without the 0x prefix.

How is an Ethereum address derived from a public key?

The address is obtained by taking the last 20 bytes of the Keccak-256 hash of the uncompressed public key. It ensures uniqueness while minimizing collision risk.

Can two different public keys produce the same Ethereum address?

Theoretically possible due to hashing, but practically impossible due to the strength of Keccak-256. The probability is negligible — far lower than winning the lottery multiple times.

Why does the public key start with 0x04?

The prefix 0x04 indicates an uncompressed public key. Compressed keys use 0x02 or 0x03 depending on the Y-coordinate parity, reducing size from 65 to 33 bytes.

Is it safe to generate private keys using standard libraries?

Yes — if you use well-audited libraries like go-ethereum/crypto. Avoid custom implementations or weak entropy sources.

Can I recover my address if I lose my wallet but have signed a message?

Yes — if you have a message and its signature made with your private key, you can recover the public key and thus your address. However, recovering the private key itself is computationally infeasible.


Mastering Ethereum’s cryptographic primitives empowers developers to build more secure and reliable applications. From generating keys to verifying signatures, each step plays a vital role in maintaining trustless integrity across the network.

👉 Explore secure wallet practices and cryptographic best practices