<p>You're basically wondering how Base58 encoding works. <a href="https://en.bitcoin.it/wiki/Base58Check_encoding" rel="nofollow">This site</a> gives a good overview but I will list the details here as well with a more concrete example. For this example, I'll just talk about the encoding, but the version byte (prepended) and checksum bytes (appended) do get added before this encoding is done. This prepending/appending just changes the base data before encoding. The below is how the data gets encoded.</p>

<p>Let's say I have this simple encoding called Base4 encoding. In my encoding:
<pre>
  0->A
  1->B
  2->C
  3->D
</pre>
If I have the number 134 (1000 0110 or 0x86) and I want to encode it in Base4, then what I do is repeatedly divide by 4 and use the encoding. Like so:</p>

<pre>
134 / 4 = 33 remainder 2 -> C
          /
   -------
  |
 33 / 4 =  8 remainder 1 -> B
          /
   -------
  |
  8 / 4 =  2 remainder 0 -> A
          /
   -------
  |
  2 / 4 =  0 remainder 2 -> C
</pre>

<p>So the Base4 encoding for this byte would be "CABC". Bitcoin does the same thing, but using 58 numbers instead of 4, and a different character for each. The characters chosen in the Base58 encoding are just to avoid confusion when humans transpose the key. For example, there is no I character, because there is already a 1 character, and the two could be confused really easily.</p>

<p>There's just one more thing that's a little tricky. If I were encoding the data 0x0086, I might want the encoding to be slightly different than the above encoding for 0x86 to show that I had an extra 0x00 byte at the beginning. To do this, all you do is add extra data at the left side of the encoding. So, in our Base4, 0x0086 is encoded as ACABC. Similarly 0x0000 0086 is encoded as AAACABC. In standard bitcoin addresses, the version byte prefix is 0x00, and 0x00 is encoded as a 1, so addresses always start with a 1.</p>

CC BY-SA 3.0
2014-08-29T08:38:31.180Z
Quick query; when you say add 0x00 what does that mean? I know 0x is shorthand for hexadecimal but when you say add 0x00 are you saying add 00 to the start of the hex value? If so why?
Wizard Of Ozzie
CC BY-SA 3.0
2014-08-29T11:30:41.667Z
0x00 means a null byte.
Pieter Wuille
CC BY-SA 3.0
2014-08-29T12:36:59.160Z
Right, 0x00 is just shorthand for the byte: 0000 0000. Base58 encoding is just for encoding some number of bytes.
morsecoder
CC BY-SA 3.0
2015-03-27T16:44:12.970Z
'Adding' might have made it unclear. For any hex string you are encoding: prefix || hex || checksum of first two parts. ANYTHING that is base58 encoded for copy/pasting does this, with a different prefix byte used for each thing you want to represent. 
BTC addresses are prefixed with 0x00. Private keys are prefixed by 0x80. P2SH addresses are prefixed by 0x05.
karimkorun
CC BY-SA 3.0
2014-08-29T03:20:44.343Z
2015-03-30T18:23:11.027Z
2015-03-30T18:23:11.027Z
morsecoder
<p>StephenM347's answer is very good, but there is one little detail he got wrong. I'd post this as a comment to his answer, but I don't have enough reputation.</p>

<p>Stephen said:</p>

<blockquote>
  <p>For example, there is no O character, because there is already a 0
  (zero) character, and the two could be confused really easily.</p>
</blockquote>

<p><a href="https://en.bitcoin.it/wiki/Base58Check_encoding" rel="nofollow">The wiki</a> says: </p>

<blockquote>
  <p>A set of 58 alphanumeric symbols consisting of easily distinguished
  uppercase and lowercase letters (0OIl are not used)</p>
</blockquote>

<p>A lowercase "o" is used, but the uppercase "O" and the number "0" are both excluded from base 58.</p>

CC BY-SA 3.0
2015-03-28T05:25:16.563Z
You are right, although I don't see why it the encoding couldn't have used at least one of the two symbols 0/O, providing the other was excluded to prevent confusion. Still, I think this is not really an answer to the question. Suggesting an edit to my original answer since this is is such a small detail, as Nick Odell has done, is a better way to go. Since you are new, your edit will have to be reviewed before it is accepted. Welcome to the bitcoin stack exchange, though, hope you can apply that close attention to detail in future answers!
morsecoder
CC BY-SA 3.0
2015-03-28T17:01:03.763Z
Ah, thanks for the tip. I didn't realise that I could suggest edits to other peoples' posts. I think the idea of avoiding both is to make it less likely that somebody with no knowledge of base 58 doesn't assume one symbol is the other when copying a WIF key down; they also avoid both the uppercase "I" and lowercase "l". Neither of them looks particularly similar to the number "1", but they could both be easily confused with each other.
JNCF
CC BY-SA 3.0
2015-03-27T19:20:54.067Z
2015-03-27T19:20:54.067Z
JNCF
<p>Here's an example of how to create a WIF with a private key using Python. It follows the docs and I've commented the code to make it enough to follow.</p>

<pre><code>import binascii, hashlib, base58

# alias method
decode_hex = binascii.unhexlify

# wallet import format key - base58 encoded format
def gen_wif_key(private_key):
    # prepended mainnet version byte to private key
    mainnet_private_key = '80' + private_key

    # perform SHA-256 hash on the mainnet_private_key
    sha256 = hashlib.sha256()
    sha256.update( decode_hex(mainnet_private_key) )
    hash = sha256.hexdigest()

    # perform SHA-256 on the previous SHA-256 hash
    sha256 = hashlib.sha256()
    sha256.update( decode_hex(hash) )
    hash = sha256.hexdigest()

    # create a checksum using the first 4 bytes of the previous SHA-256 hash
    # append the 4 checksum bytes to the mainnet_private_key
    checksum = hash[:8]
    hash = mainnet_private_key + checksum

    # convert mainnet_private_key + checksum into base58 encoded string
    return base58.b58encode( decode_hex(hash) )
</code></pre>

CC BY-SA 3.0
2017-11-23T23:13:22.313Z
2017-11-23T23:13:22.313Z
shmuli
<p>simplest way</p>
<pre class="lang-py prettyprint-override"><code>from bit import Key

# Import wif format:
privKey = Key.('L1VotKmtZRLZSnSPhLhQxfts2aqBMru2APTs4Yuc8TYJ4jNhQoGB')



# Export hex format:

privKey = Key.to_hex()

# Export int format:

privKey = Key.to_int()


# Export to bytes
privKey = Key.to_bytes()

</code></pre>

CC BY-SA 4.0
2022-12-15T16:32:42.943Z
2022-12-15T16:32:42.943Z
fredsta98
<p>To convert command-line given string to WIF, where the parameter could be hex number or any rational string, you can use this script to get one conversion:</p>
<pre><code>#!/usr/bin/env python3
import base58
import hashlib
import sys

def b58(hex):
    return base58.b58encode_check(hex)

def sha256(hex):
    return hashlib.sha256(hex).digest()

def main():
    k = sha256(str(sys.argv[1]).encode('utf-8'))
    extend = '80' + k.hex()
    print(b58(bytes.fromhex(extend)).decode('utf-8'))

if __name__ == '__main__':
    main()
</code></pre>
<p>Save the above file as priv2wif.py and run with 1 parameter. If your string have spaces in it, put whole string into &quot;&quot;.</p>
<p>For massive conversion you can use second script in the same folder:</p>
<pre><code>#!/usr/bin/env bash
&gt; output.txt
while IFS= read -r p; do
    ./priv2wif.py &quot;$p&quot; &gt;&gt; output.txt
    echo -n .
done &lt; &quot;input.txt&quot;
</code></pre>
<p>Save this file with no extension. You should make <code>input.txt</code> file with one string per line (watch out for CR/LF, as you should use LF only //Linux//) and after running the script you will get all your WIF keys in output.txt one per line.</p>

CC BY-SA 4.0
2020-06-22T15:25:59.323Z
2020-06-22T15:25:59.323Z
pbies
<p>Based on the following link:  <a href="https://en.bitcoin.it/wiki/Wallet_import_format" rel="nofollow">https://en.bitcoin.it/wiki/Wallet_import_format</a> , a private key of 256 bits gets transformed into a WIF address that is stored in the wallet.</p>

<p>However, my question here is how did we convert step 6 into step 7? In step 6, the address consists of 74 hexadecimals characters (or 74*4= 296 bits). If we convert this 296 bits address using the code58, we need to divide 296 bits by 6.. ? I believe that some details are not mentioned, any ideas?</p>

<wallet><private-key><wallet-import-format>
Private key to WIF
anapaso
# Private key to WIF

(Asked by: username_0 on 2013-04-06)

Based on the following link: <https://en.bitcoin.it/wiki/Wallet_import_format> , a private key of 256 bits gets transformed into a WIF address that is stored in the wallet.

However, my question here is how did we convert step 6 into step 7? In step 6, the address consists of 74 hexadecimals characters (or 74\*4= 296 bits). If we convert this 296 bits address using the code58, we need to divide 296 bits by 6.. ? I believe that some details are not mentioned, any ideas?

**Tags:** wallet, private-key, wallet-import-format


---

## 5 answers

### Answer by username_1 on 2014-08-29. Score: 1

You're basically wondering how Base58 encoding works. [This site](https://en.bitcoin.it/wiki/Base58Check_encoding) gives a good overview but I will list the details here as well with a more concrete example. For this example, I'll just talk about the encoding, but the version byte (prepended) and checksum bytes (appended) do get added before this encoding is done. This prepending/appending just changes the base data before encoding. The below is how the data gets encoded.

Let's say I have this simple encoding called Base4 encoding. In my encoding:

```

  0->A
  1->B
  2->C
  3->D

```

If I have the number 134 (1000 0110 or 0x86) and I want to encode it in Base4, then what I do is repeatedly divide by 4 and use the encoding. Like so:

```

134 / 4 = 33 remainder 2 -> C
          /
   -------
  |
 33 / 4 =  8 remainder 1 -> B
          /
   -------
  |
  8 / 4 =  2 remainder 0 -> A
          /
   -------
  |
  2 / 4 =  0 remainder 2 -> C

```

So the Base4 encoding for this byte would be "CABC". Bitcoin does the same thing, but using 58 numbers instead of 4, and a different character for each. The characters chosen in the Base58 encoding are just to avoid confusion when humans transpose the key. For example, there is no I character, because there is already a 1 character, and the two could be confused really easily.

There's just one more thing that's a little tricky. If I were encoding the data 0x0086, I might want the encoding to be slightly different than the above encoding for 0x86 to show that I had an extra 0x00 byte at the beginning. To do this, all you do is add extra data at the left side of the encoding. So, in our Base4, 0x0086 is encoded as ACABC. Similarly 0x0000 0086 is encoded as AAACABC. In standard bitcoin addresses, the version byte prefix is 0x00, and 0x00 is encoded as a 1, so addresses always start with a 1.

> **Comments:**
> **username_2**: Quick query; when you say add 0x00 what does that mean? I know 0x is shorthand for hexadecimal but when you say add 0x00 are you saying add 00 to the start of the hex value? If so why?  
> **username_3**: 0x00 means a null byte.  
> **username_1**: Right, 0x00 is just shorthand for the byte: 0000 0000. Base58 encoding is just for encoding some number of bytes.  
> **username_4**: 'Adding' might have made it unclear. For any hex string you are encoding: prefix || hex || checksum of first two parts. ANYTHING that is base58 encoded for copy/pasting does this, with a different prefix byte used for each thing you want to represent.  BTC addresses are prefixed with 0x00. Private keys are prefixed by 0x80. P2SH addresses are prefixed by 0x05.  

---

### Answer by username_5 on 2015-03-27. Score: 1

StephenM347's answer is very good, but there is one little detail he got wrong. I'd post this as a comment to his answer, but I don't have enough reputation.

Stephen said:

> For example, there is no O character, because there is already a 0
> (zero) character, and the two could be confused really easily.

[The wiki](https://en.bitcoin.it/wiki/Base58Check_encoding) says:

> A set of 58 alphanumeric symbols consisting of easily distinguished
> uppercase and lowercase letters (0OIl are not used)

A lowercase "o" is used, but the uppercase "O" and the number "0" are both excluded from base 58.

> **Comments:**
> **username_1**: You are right, although I don't see why it the encoding couldn't have used at least one of the two symbols 0/O, providing the other was excluded to prevent confusion. Still, I think this is not really an answer to the question. Suggesting an edit to my original answer since this is is such a small detail, as Nick Odell has done, is a better way to go. Since you are new, your edit will have to be reviewed before it is accepted. Welcome to the bitcoin stack exchange, though, hope you can apply that close attention to detail in future answers!  
> **username_5**: Ah, thanks for the tip. I didn't realise that I could suggest edits to other peoples' posts. I think the idea of avoiding both is to make it less likely that somebody with no knowledge of base 58 doesn't assume one symbol is the other when copying a WIF key down; they also avoid both the uppercase "I" and lowercase "l". Neither of them looks particularly similar to the number "1", but they could both be easily confused with each other.  

---

### Answer by username_6 on 2017-11-23. Score: 1

Here's an example of how to create a WIF with a private key using Python. It follows the docs and I've commented the code to make it enough to follow.

```
import binascii, hashlib, base58

# alias method
decode_hex = binascii.unhexlify

# wallet import format key - base58 encoded format
def gen_wif_key(private_key):
    # prepended mainnet version byte to private key
    mainnet_private_key = '80' + private_key

    # perform SHA-256 hash on the mainnet_private_key
    sha256 = hashlib.sha256()
    sha256.update( decode_hex(mainnet_private_key) )
    hash = sha256.hexdigest()

    # perform SHA-256 on the previous SHA-256 hash
    sha256 = hashlib.sha256()
    sha256.update( decode_hex(hash) )
    hash = sha256.hexdigest()

    # create a checksum using the first 4 bytes of the previous SHA-256 hash
    # append the 4 checksum bytes to the mainnet_private_key
    checksum = hash[:8]
    hash = mainnet_private_key + checksum

    # convert mainnet_private_key + checksum into base58 encoded string
    return base58.b58encode( decode_hex(hash) )

```


---

### Answer by username_7 on 2022-12-15. Score: 0

simplest way

```py
from bit import Key

# Import wif format:
privKey = Key.('L1VotKmtZRLZSnSPhLhQxfts2aqBMru2APTs4Yuc8TYJ4jNhQoGB')

# Export hex format:

privKey = Key.to_hex()

# Export int format:

privKey = Key.to_int()

# Export to bytes
privKey = Key.to_bytes()

```


---

### Answer by username_8 on 2020-06-22. Score: 0

To convert command-line given string to WIF, where the parameter could be hex number or any rational string, you can use this script to get one conversion:

```
#!/usr/bin/env python3
import base58
import hashlib
import sys

def b58(hex):
    return base58.b58encode_check(hex)

def sha256(hex):
    return hashlib.sha256(hex).digest()

def main():
    k = sha256(str(sys.argv[1]).encode('utf-8'))
    extend = '80' + k.hex()
    print(b58(bytes.fromhex(extend)).decode('utf-8'))

if __name__ == '__main__':
    main()

```

Save the above file as priv2wif.py and run with 1 parameter. If your string have spaces in it, put whole string into "".

For massive conversion you can use second script in the same folder:

```
#!/usr/bin/env bash
> output.txt
while IFS= read -r p; do
    ./priv2wif.py "$p" >> output.txt
    echo -n .
done < "input.txt"

```

Save this file with no extension. You should make `input.txt` file with one string per line (watch out for CR/LF, as you should use LF only //Linux//) and after running the script you will get all your WIF keys in output.txt one per line.


---

