Despite the name, an Ethereum wallet does not "hold" your coins. Your ETH lives on the blockchain itself, recorded in a global state that every node maintains. What a wallet actually holds is a private key, a 256-bit random number that gives you the exclusive ability to authorize transactions from your account. From this single private key, the wallet derives your public key using elliptic curve multiplication on the secp256k1 curve, and from the public key it derives your address by taking the last 20 bytes of a Keccak-256 hash. This one-way derivation chain means anyone can verify that a signature came from your address, but nobody can reverse-engineer your private key from your address or public key.
Everything starts with a private key: 256 bits of randomness, typically generated by a cryptographically secure random number generator. This key must remain secret at all times. If anyone obtains your private key, they can sign transactions on your behalf and drain your account.
The wallet then performs elliptic curve multiplication on the secp256k1 curve to derive the public key. This is a one-way mathematical operation: it is computationally infeasible to recover the private key from the public key. The public key is a 512-bit number (64 bytes) representing a point on the curve.
Finally, the wallet computes the Keccak-256 hash of the public key and takes the last 20 bytes (160 bits) of the result. This gives you your Ethereum address, the 0x71C7... identifier that other people use to send you ETH or interact with your contracts.
When you want to send a transaction, your wallet constructs a transaction object containing the recipient address, value, gas limit, gas price, nonce, and optionally some calldata (used when interacting with smart contracts). Here is what happens next:
The transaction fields are serialized using Recursive Length Prefix (RLP) encoding, which is Ethereum's standard serialization format. This produces a compact byte string representation of the transaction.
The RLP-encoded transaction is then passed through the Keccak-256 hash function, producing a 32-byte hash. This hash is what actually gets signed, not the raw transaction data. Signing a fixed-length hash is both more efficient and more secure than signing arbitrary-length data.
The wallet uses the Elliptic Curve Digital Signature Algorithm (ECDSA) with the secp256k1 curve to sign the hash using your private key. The signing process produces three values:
r and s: the two components of the ECDSA signature (each 32 bytes)v: the recovery identifier, which allows anyone to recover the public key (and therefore the sender's address) from the signature aloneThe original transaction data is combined with the signature components (v, r, s) and RLP-encoded again. The result is a signed raw transaction, a hex string that can be broadcast to the network via eth_sendRawTransaction. Any Ethereum node can then verify the signature, recover the sender's address, and confirm the transaction is legitimate without ever needing to know the private key.
// Simplified signing flow using go-ethereum (geth)
import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/rlp"
)
// 1. Build the transaction
tx := types.NewTransaction(
nonce, // account nonce
toAddress, // recipient
value, // ETH in wei
gasLimit, // gas limit
gasPrice, // gas price
data, // calldata
)
// 2. RLP-encode and hash (Keccak-256)
signer := types.NewEIP155Signer(chainID)
hash := signer.Hash(tx) // keccak256(rlp(tx fields))
// 3. ECDSA sign with private key --> (v, r, s)
signature, _ := crypto.Sign(hash.Bytes(), privateKey)
// 4. Attach signature to transaction
signedTx, _ := tx.WithSignature(signer, signature)
// 5. RLP-encode the signed transaction --> ready to broadcast
rawTx, _ := rlp.EncodeToBytes(signedTx)
The beauty of this design is that your private key never leaves your device. When you use MetaMask or a hardware wallet like Ledger, the signing happens locally. The RPC provider or Ethereum node only ever receives the already-signed transaction. They can verify its authenticity, but they can never forge a new one. This is why protecting your private key (or seed phrase, from which the private key is derived) is the single most important security practice in crypto.
To see what happens after the signed transaction is broadcast, check out Sending Transactions on Ethereum.