<p>Bitcoin private keys are most commonly displayed in wallet import format (WIF), also known as base58check (a number expressed in base 58 with a checksum at the end and a version byte at the beginning).</p>

<p>To create a WIF private key, you need to:</p>

<ol>
<li>Generate an ECDSA secret exponent (the private key) using the SECP256k1 curve.</li>
<li>Convert the secret exponent/private key into base58check format.</li>
</ol>

<p>Here are two simple ways to generate a secret exponent:</p>

<ol>
<li>Select a random number in the range [1, curve_order).</li>
<li>Generate a random 64-character hexidecimal string (the hex string representation of a 256-bit number) and check to make sure that the number is in the range [1, curve_order). Repeat if necessary.</li>
</ol>

<p>For SECP256k1, the curve order is 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140 (or 115792089237316195423570985008687907852837564279074904382605163141518161494336L).</p>

<p>This number is extremely close to the largest 256-bit number (0xFFF...FFF in hex), so you can expect that you'll never exceed the curve order if you generate a random 256-bit number.</p>

<p>As Pieter Wuille mentioned, public keys are derived by performing point multiplication with the curve's base point and the secret exponent/private key. The resulting (x,y) coordinate is the public key.</p>

<p>The Bitcoin address, just like the private key, is also displayed in base58check format. To get the address, we do the following:</p>

<ol>
<li>Calculate the hash160: ripemd160(sha256(public_key)).</li>
<li>Convert the hash160 to base58check format.</li>
</ol>

<p>To convert a number to base58check format, just perform the following steps:</p>

<ol>
<li>convert the value to a byte array and append the version byte to the beginning</li>
<li>calculate the first 4 bytes of SHA256(SHA256(result of step 1)) and call it the checksum</li>
<li>append the checksum to the end of the result of step 1</li>
<li>move the result of step 3 to the keyspace "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"</li>
<li>check how many leading zeros the original binary value had and append those to the beginning of the result of step 4</li>
</ol>

<p>Here are the <a href="https://en.bitcoin.it/wiki/Base58Check_encoding#Creating_a_Base58Check_string">more detailed instructions</a>.</p>

<p>Now if you don't want to worry about any of this stuff, I would check out the python library Coinkit (<a href="https://github.com/halfmoonlabs/coinkit">https://github.com/halfmoonlabs/coinkit</a> or "pip install coinkit").</p>

<p>You can perform simple operations like these:</p>

<pre><code>&gt;&gt;&gt; from coinkit.keypair import BitcoinKeypair
&gt;&gt;&gt; hex_private_key = '91149ee24f1ee9a6f42c3dd64c2287781c8c57a6e8e929c80976e586d5322a3d'
&gt;&gt;&gt; k = BitcoinKeypair(hex_private_key)
&gt;&gt;&gt; k.private_key()
'91149ee24f1ee9a6f42c3dd64c2287781c8c57a6e8e929c80976e586d5322a3d'
&gt;&gt;&gt; k.public_key()
'042c6b7e6da7633c8f226891cc7fa8e5ec84f8eacc792a46786efc869a408d29539a5e6f8de3f71c0014e8ea71691c7b41f45c083a074fef7ab5c321753ba2b3fe'
&gt;&gt;&gt; k.wif_pk()
'5JvBUBPzU42Y7BHD7thTnySXQXMk8XEJGGQGcyBw7CCkw8RAH7m'
&gt;&gt;&gt; k.address()
'13mtgVARiB1HiRyCHnKTi6rEwyje5TYKBW'
</code></pre>

<p>You can also create random keypairs:</p>

<pre><code>&gt;&gt;&gt; k = BitcoinKeypair()
</code></pre>

<p>And brain wallet keypairs:</p>

<pre><code>&gt;&gt;&gt; passphrase = 'shepherd mais pack rate enamel horace diva filesize maximum really roar mall'
&gt;&gt;&gt; k = BitcoinKeypair().from_passphrase(passphrase)
&gt;&gt;&gt; k.passphrase()
'shepherd mais pack rate enamel horace diva filesize maximum really roar mall'
</code></pre>

<p>Disclosure: I'm one of the creators of Coinkit.</p>

CC BY-SA 3.0
2014-01-03T20:59:18.033Z
2014-01-15T18:05:53.610Z
2014-01-15T18:05:53.610Z
Ryan Shea
<p>As is normal when doing Elliptic Curve encryption, a private key is simply a random number. In the case of secp256k1, the elliptic curve used by Bitcoin, it has to be a number between 1 and 115792089237316195423570985008687907852837564279074904382605163141518161494336 (or in hexadecimal, between <code>0x1</code> and <code>0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364140</code>).</p>

<p>This private key is converted to a public key by performing an EC point multiplication with the curve's base point. The result is an <code>(x,y)</code> coordinate pair, which constitutes the public key.</p>

<p>Finally, <code>RIPEMD160(SHA256(pubkey))</code>, where pubkey is a serialization of those coordinates, is computed, and encoded in base58, together with a checksum. This becomes the address.</p>

CC BY-SA 3.0
2013-03-18T20:19:40.887Z
How did you determine this was the maximum value?  I'd like to learn both the right / wrong way so I can learn from your [edits] ;)
makerofthings7
CC BY-SA 3.0
2013-03-19T01:26:44.993Z
I copied it from https://en.bitcoin.it/wiki/Secp256k1, which itself copied it from the SEC2 specification document: http://www.secg.org/collateral/sec2_final.pdf
Pieter Wuille
CC BY-SA 3.0
2016-05-18T08:19:46.953Z
Updated link to SEC2 document http://www.secg.org/SEC2-Ver-1.0.pdf
Walter K
CC BY-SA 4.0
2018-05-11T20:26:58.933Z
Are either of those two steps reversible?
zylstra
CC BY-SA 4.0
2018-05-12T01:01:39.307Z
No, they're not (as long as ECDLP is hard).
Pieter Wuille
CC BY-SA 3.0
2011-10-24T11:41:51.760Z
2014-01-20T09:12:52.180Z
2014-01-20T09:12:52.180Z
Pieter Wuille
<p>The Javascript code from: <a href="http://www.bitaddress.org" rel="nofollow">http://www.bitaddress.org</a> might give you a good example of this as well.</p>

CC BY-SA 3.0
2011-10-06T23:18:15.730Z
2011-10-06T23:18:15.730Z
Stephen Gornick
<p>How they are created is fully documented <a href="https://en.bitcoin.it/wiki/Address" rel="nofollow">on wiki</a>: <a href="https://en.bitcoin.it/wiki/Technical_background_of_Bitcoin_addresses" rel="nofollow">https://en.bitcoin.it/wiki/Technical_background_of_Bitcoin_addresses</a></p>

<p><strong>In Java</strong></p>

<ol>
<li>Include <a href="https://github.com/bitcoinj/bitcoinj/releases/latest" rel="nofollow">the jar of bitcoinj Java library</a> in your classpath</li>
<li><p>The code:</p>

<pre><code>import com.google.bitcoin.core.*;

NetworkParameters params = new MainNetParams();

String publicAddress = new DumpedPrivateKey(params,
        "KzzuoFPzrPhD55icpAi7idW7z7tH8xSYo3xqTcZm3fHk3AzVxpoP").getKey()
        .toAddress(params).toString();
</code></pre></li>
<li><p>The result is <code>17vFi4XjRibQPCktoMcGhZ3DmnG85r1VHE</code>.</p></li>
</ol>

<p><strong>In JavaScript</strong></p>

<p>Using <a href="https://github.com/pointbiz/bitaddress.org" rel="nofollow">bitaddress.org</a> javascript library:</p>

<pre><code>var key = new Bitcoin.ECKey('KzzuoFPzrPhD55icpAi7idW7z7tH8xSYo3xqTcZm3fHk3AzVxpoP');
console.log(key.getBitcoinAddress());
</code></pre>

<p>The result is <code>17vFi4XjRibQPCktoMcGhZ3DmnG85r1VHE</code>.</p>

<hr>

<p>Note 1: Before, I did <code>bitcoin-cli getnewaddress</code> and <code>bitcoin-cli dumpprivkey &lt;pubkey&gt;</code> to get the key pair.</p>

<p>Note 2: To make things even more easy, under your directory <a href="https://github.com/pointbiz/bitaddress.org/tree/master/src" rel="nofollow">https://github.com/pointbiz/bitaddress.org/tree/master/src</a> just run:</p>

<pre><code>cat array.map.js cryptojs.js cryptojs.sha256.js cryptojs.pbkdf2.js cryptojs.hmac.js cryptojs.aes.js cryptojs.blockmodes.js cryptojs.ripemd160.js securerandom.js ellipticcurve.js secrets.js biginteger.js qrcode.js bitcoinjs-lib.js bitcoinjs-lib.base58.js bitcoinjs-lib.address.js bitcoinjs-lib.ecdsa.js bitcoinjs-lib.eckey.js bitcoinjs-lib.util.js crypto-scrypt.js &gt; all.js
</code></pre>

<p>and you get a 174kb file that is all you need to run.</p>

<p>Note 3: If you want to get this file (from commit f6c6bbe53df28c1bf51a6216f02ad1467b36c9f7) look here: <a href="http://pastebin.com/raw.php?i=rH8V2j9H" rel="nofollow">http://pastebin.com/raw.php?i=rH8V2j9H</a></p>

<hr>

<p><strong>The full functional example</strong></p>

<pre><code>&lt;!DOCTYPE HTML&gt;
&lt;html&gt;

&lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;script type="text/javascript" src="http://pastebin.com/raw.php?i=rH8V2j9H"&gt;&lt;/script&gt;
&lt;/head&gt;

&lt;body&gt;
    &lt;form onsubmit="alert(new Bitcoin.ECKey(document.getElementById('pkey').value).getBitcoinAddress());"&gt;
        &lt;label&gt;
            Private key:
            &lt;input id="pkey" type="text"&gt;
        &lt;/label&gt;
    &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>

CC BY-SA 3.0
2014-07-31T19:54:02.997Z
2014-08-20T03:59:05.403Z
2014-08-20T03:59:05.403Z
Felipe
<p>The public and private keys in a Bitcoin address are a normal <a href="http://en.wikipedia.org/wiki/Elliptic_Curve_DSA">ECDSA</a> key pair. I haven't poked through this particular bit of Bitcoin's own code but the offshoot products I've had a chance to work with typically use the <a href="http://www.bouncycastle.org">Bouncy Castle</a> crypto library. Bouncy Castle also has an <a href="http://www.bouncycastle.org/wiki/display/JA1/Elliptic+Curve+Key+Pair+Generation+and+Key+Factories">excellent introduction/tutorial</a> on how to use their library. Their examples are in Java but it's fairly simple and should be easily ported to other languages.</p>

<p>There is also an excellent <a href="http://www-cs-students.stanford.edu/~tjw/jsbn/">pre-written library</a> for JavaScript key generation available from Tom Wu under the BSD license.</p>

CC BY-SA 3.0
2011-10-06T23:20:13.297Z
2011-10-06T23:20:13.297Z
David Perry
<p>I understand the high level concept I am more interested specific details.   How is a private key generated.  How exactly is public key generated, how is address generated from public key.</p>

<address><private-key><public-key><address-generation>
How are public & private keys in an address created?
DeathAndTaxes
# How are public & private keys in an address created?

(Asked by: username_0 on 2011-10-06)

I understand the high level concept I am more interested specific details. How is a private key generated. How exactly is public key generated, how is address generated from public key.

**Tags:** address, private-key, public-key, address-generation


---

## 5 answers

### Answer by username_8 on 2011-10-06. Score: 10 | Accepted answer

The public and private keys in a Bitcoin address are a normal [ECDSA](http://en.wikipedia.org/wiki/Elliptic_Curve_DSA) key pair. I haven't poked through this particular bit of Bitcoin's own code but the offshoot products I've had a chance to work with typically use the [Bouncy Castle](http://www.bouncycastle.org) crypto library. Bouncy Castle also has an [excellent introduction/tutorial](http://www.bouncycastle.org/wiki/display/JA1/Elliptic+Curve+Key+Pair+Generation+and+Key+Factories) on how to use their library. Their examples are in Java but it's fairly simple and should be easily ported to other languages.

There is also an excellent [pre-written library](http://www-cs-students.stanford.edu/~tjw/jsbn/) for JavaScript key generation available from Tom Wu under the BSD license.


---

### Answer by username_2 on 2011-10-24. Score: 29

As is normal when doing Elliptic Curve encryption, a private key is simply a random number. In the case of secp256k1, the elliptic curve used by Bitcoin, it has to be a number between 1 and 115792089237316195423570985008687907852837564279074904382605163141518161494336 (or in hexadecimal, between `0x1` and `0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364140`).

This private key is converted to a public key by performing an EC point multiplication with the curve's base point. The result is an `(x,y)` coordinate pair, which constitutes the public key.

Finally, `RIPEMD160(SHA256(pubkey))`, where pubkey is a serialization of those coordinates, is computed, and encoded in base58, together with a checksum. This becomes the address.

> **Comments:**
> **username_3**: How did you determine this was the maximum value?  I'd like to learn both the right / wrong way so I can learn from your [edits] ;)  
> **username_2**: I copied it from https://en.bitcoin.it/wiki/Secp256k1, which itself copied it from the SEC2 specification document: http://www.secg.org/collateral/sec2_final.pdf  
> **username_4**: Updated link to SEC2 document http://www.secg.org/SEC2-Ver-1.0.pdf  
> **username_5**: Are either of those two steps reversible?  
> **username_2**: No, they're not (as long as ECDLP is hard).  

---

### Answer by username_1 on 2014-01-03. Score: 10

Bitcoin private keys are most commonly displayed in wallet import format (WIF), also known as base58check (a number expressed in base 58 with a checksum at the end and a version byte at the beginning).

To create a WIF private key, you need to:

1. Generate an ECDSA secret exponent (the private key) using the SECP256k1 curve.
2. Convert the secret exponent/private key into base58check format.

Here are two simple ways to generate a secret exponent:

1. Select a random number in the range [1, curve\_order).
2. Generate a random 64-character hexidecimal string (the hex string representation of a 256-bit number) and check to make sure that the number is in the range [1, curve\_order). Repeat if necessary.

For SECP256k1, the curve order is 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140 (or 115792089237316195423570985008687907852837564279074904382605163141518161494336L).

This number is extremely close to the largest 256-bit number (0xFFF...FFF in hex), so you can expect that you'll never exceed the curve order if you generate a random 256-bit number.

As username_2 username_2 mentioned, public keys are derived by performing point multiplication with the curve's base point and the secret exponent/private key. The resulting (x,y) coordinate is the public key.

The Bitcoin address, just like the private key, is also displayed in base58check format. To get the address, we do the following:

1. Calculate the hash160: ripemd160(sha256(public\_key)).
2. Convert the hash160 to base58check format.

To convert a number to base58check format, just perform the following steps:

1. convert the value to a byte array and append the version byte to the beginning
2. calculate the first 4 bytes of SHA256(SHA256(result of step 1)) and call it the checksum
3. append the checksum to the end of the result of step 1
4. move the result of step 3 to the keyspace "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
5. check how many leading zeros the original binary value had and append those to the beginning of the result of step 4

Here are the [more detailed instructions](https://en.bitcoin.it/wiki/Base58Check_encoding#Creating_a_Base58Check_string).

Now if you don't want to worry about any of this stuff, I would check out the python library Coinkit (<https://github.com/halfmoonlabs/coinkit> or "pip install coinkit").

You can perform simple operations like these:

```
>>> from coinkit.keypair import BitcoinKeypair
>>> hex_private_key = '91149ee24f1ee9a6f42c3dd64c2287781c8c57a6e8e929c80976e586d5322a3d'
>>> k = BitcoinKeypair(hex_private_key)
>>> k.private_key()
'91149ee24f1ee9a6f42c3dd64c2287781c8c57a6e8e929c80976e586d5322a3d'
>>> k.public_key()
'042c6b7e6da7633c8f226891cc7fa8e5ec84f8eacc792a46786efc869a408d29539a5e6f8de3f71c0014e8ea71691c7b41f45c083a074fef7ab5c321753ba2b3fe'
>>> k.wif_pk()
'5JvBUBPzU42Y7BHD7thTnySXQXMk8XEJGGQGcyBw7CCkw8RAH7m'
>>> k.address()
'13mtgVARiB1HiRyCHnKTi6rEwyje5TYKBW'

```

You can also create random keypairs:

```
>>> k = BitcoinKeypair()

```

And brain wallet keypairs:

```
>>> passphrase = 'shepherd mais pack rate enamel horace diva filesize maximum really roar mall'
>>> k = BitcoinKeypair().from_passphrase(passphrase)
>>> k.passphrase()
'shepherd mais pack rate enamel horace diva filesize maximum really roar mall'

```

Disclosure: I'm one of the creators of Coinkit.


---

### Answer by username_6 on 2011-10-06. Score: 4

The Javascript code from: <http://www.bitaddress.org> might give you a good example of this as well.


---

### Answer by username_7 on 2014-07-31. Score: 1

How they are created is fully documented [on wiki](https://en.bitcoin.it/wiki/Address): <https://en.bitcoin.it/wiki/Technical_background_of_Bitcoin_addresses>

**In Java**

1. Include [the jar of bitcoinj Java library](https://github.com/bitcoinj/bitcoinj/releases/latest) in your classpath
2. The code:

   ```
   import com.google.bitcoin.core.*;

   NetworkParameters params = new MainNetParams();

   String publicAddress = new DumpedPrivateKey(params,
           "KzzuoFPzrPhD55icpAi7idW7z7tH8xSYo3xqTcZm3fHk3AzVxpoP").getKey()
           .toAddress(params).toString();

   ```
3. The result is `17vFi4XjRibQPCktoMcGhZ3DmnG85r1VHE`.

**In JavaScript**

Using [bitaddress.org](https://github.com/pointbiz/bitaddress.org) javascript library:

```
var key = new Bitcoin.ECKey('KzzuoFPzrPhD55icpAi7idW7z7tH8xSYo3xqTcZm3fHk3AzVxpoP');
console.log(key.getBitcoinAddress());

```

The result is `17vFi4XjRibQPCktoMcGhZ3DmnG85r1VHE`.

---

Note 1: Before, I did `bitcoin-cli getnewaddress` and `bitcoin-cli dumpprivkey <pubkey>` to get the key pair.

Note 2: To make things even more easy, under your directory <https://github.com/pointbiz/bitaddress.org/tree/master/src> just run:

```
cat array.map.js cryptojs.js cryptojs.sha256.js cryptojs.pbkdf2.js cryptojs.hmac.js cryptojs.aes.js cryptojs.blockmodes.js cryptojs.ripemd160.js securerandom.js ellipticcurve.js secrets.js biginteger.js qrcode.js bitcoinjs-lib.js bitcoinjs-lib.base58.js bitcoinjs-lib.address.js bitcoinjs-lib.ecdsa.js bitcoinjs-lib.eckey.js bitcoinjs-lib.util.js crypto-scrypt.js > all.js

```

and you get a 174kb file that is all you need to run.

Note 3: If you want to get this file (from commit f6c6bbe53df28c1bf51a6216f02ad1467b36c9f7) look here: <http://pastebin.com/raw.php?i=rH8V2j9H>

---

**The full functional example**

```
<!DOCTYPE HTML>
<html>

<head>
    <meta charset="UTF-8">
    <script type="text/javascript" src="http://pastebin.com/raw.php?i=rH8V2j9H"></script>
</head>

<body>
    <form onsubmit="alert(new Bitcoin.ECKey(document.getElementById('pkey').value).getBitcoinAddress());">
        <label>
            Private key:
            <input id="pkey" type="text">
        </label>
    </form>
</body>
</html>

```


---

