# How are different addresses generated from the same private key?

I was reading in the "Technical background of version 1 Bitcoin addresses" that addresses are a function of the private key. More or less:

Private Key -> Public Key -> Address


If the public key is the only input needed to generate an address, how come a wallet generates a different address every time? What is changing?

• possible duplicate of What is a deterministic wallet?
– Murch
Commented Aug 30, 2016 at 17:09
• A deterministic wallet is a way to generate a private key from a passphrase.The question here is that it seems that different addresses can be generated from a single private key. At least that is the impression, my wallet manager gives me. Commented Aug 30, 2016 at 17:49
• Ok, now I see it. The answer are Sequential or Hierarchical Deterministic Wallets. This awnser explains it: bitcoin.stackexchange.com/questions/718/… Commented Aug 30, 2016 at 17:55
• Rather than delve into complex math, let us use an already existing and handy command line Linux password generator tool called pwgen. You can give pwgen a seed file and it will always spit out the same set of passwords, for example in thousands. Here is how: bash echo "sowing the seeds of love" > /tmp/seedfile.txt pwgen -H /tmp/seedfile.txt -N 1000  Commented Jun 27, 2018 at 7:23

Private and public key correspond to a point on the secp256k1 curve. They have a one-to-one relationship.

The address is derived from the public key by performing a ripemd160 hash after a sha256 hash on the public key. Multiple public keys hash to the same address, as the address space is only 160 bit, while the public key space is 256 bit.

Since both derivations (private key > public key > address) are deterministic, you cannot derive more than one address from one private key.*

What you can do, is derive additional private keys from a "master private key" with a given derivation rule. These additional private keys obviously correspond to new addresses. This type of address management is called "hierarchical deterministic wallet".

*Strictly speaking, you can create multiple addresses by differentiating between compressed and uncompressed keys. See Sven's and skaht's answers for details.

With Bitcoin, a single private key will have associated compressed and uncompressed private/public key pairs. Uncompressed public key addresses are larger in size than newer compressed public addresses. (Contrast 1b and 2b below.) Uncompressed and compressed public keys shall have different associated Bitcoin addresses. Private keys encoded in wallet input format (WIF) will implicitly communicate to a hot wallet if uncompressed or compressed keys are to be used. A Blockchain records funds sent to either address uncompressed or compressed independently.

Here are illustrative examples using libbitcoin's bitcoin-explorer (bx) command line interface using one of the absolute worst hexadecimal encoded private keys in the world 0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff that is obviously 256 bits in length.

1a) Uncompressed Private Key WIF-encoded:

% echo "0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff" | bx base58check-encode -v 128

5HpHb4pzVWwsDAHNwwUS3VViCkwzcutaSJ57T4GNFw5UBNLSrRV

1b) Uncompressed Public Key:

% echo "0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff" | bx ec-to-public -u

040d47568a5e517067a2836c3823fbc58169a7662bfae934a4d41da3e23c98d816e7202dd702ffe038147f78aee4973a581972960a1460312ffb6f3f0f13d4a52c

% echo "0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff" | bx ec-to-public -u | bx ec-to-address -v 0

1NGoV1EGZrwM7yvUYqRC7TMBMj7ftpjR2B

2a) Compressed Private Key WIF-encoded:

% echo "0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff01" | bx base58check-encode -v 128

KwDiDMtpksBAcfyHsVS5XzmirtyjKWSeaeM9U1QppugixMUeKMqp

2b) Compressed Public Key:

% echo "0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff" | bx ec-to-public

020d47568a5e517067a2836c3823fbc58169a7662bfae934a4d41da3e23c98d816

% echo "0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff" | bx ec-to-public | bx ec-to-address -v 0

1PbStXjfDNBU6FZA2iSeisVWwCFN9GK1eQ <- No bot was fast enough here to intercept my experimentation

Whenever you are attempting to explain Bitcoin to anyone, it makes a lot of sense to simply state that the derivation private key > public key > address is deterministic. However, if you are interested in writing your own code or studying the existing code base from various libraries, you may wish to know that a private key can actually lead to two public keys (one in compressed form and another in uncompressed form), both being encodings of the same point on the secp256k1 elliptic curve but leading to two different hash values. Hence, we have two possible hash values and each hash value can in turn lead to two different (pay-to-public-key-hash) addresses (one for the main bitcoin network and one for the testing network). So all in all (from a developer perspective rather than a mere user of Bitcoin), a private key can lead to 4 possible addresses. I attach a java snippet:

import java.math.BigInteger;
import org.bitcoinj.core.ECKey;
import org.bitcoinj.core.NetworkParameters;
import org.bitcoinj.params.MainNetParams;
import org.bitcoinj.params.TestNet3Params;

public class Test {

public static void main(String[] args){

// An example of private key from the book 'Mastering Bitcoin'
String k = "1E99423A4ED27608A15A2616A2B0E9E52CED330AC530EDCC32C8FFC6A526AEDD";

// Converting our string encoding as an actual number
BigInteger priv = new BigInteger(k,16);

// Creating a key object from our private key, with compressed public key
ECKey k1 = ECKey.fromPrivate(priv, true);

// Creating a key object from our private key, with uncompressed public key
ECKey k2 = ECKey.fromPrivate(priv, false);

System.out.println(k1.getPublicKeyAsHex()); // compressed

//...07cf33da18bd734c600b96a72bbc4749d5141c90ec8ac328ae52ddfe2e505bdb
System.out.println(k2.getPublicKeyAsHex()); // uncompressed

NetworkParameters main = MainNetParams.get();   // main bitcoin network
NetworkParameters test = TestNet3Params.get();  // test bitcoin network