WIF Private Key | Wallet Import Format (2024)

Wallet Import Format

  • WIF Private Key | Wallet Import Format (1)Greg Walker
  • WIF Private Key | Wallet Import Format (2)
  • Download PDF

A WIF (Wallet Import Format) private key is an address-style format for a private key.

It's used when exporting and importing private keys between bitcoin wallets.

It's mainly a Base58 encoding of the private key, but also includes some extra useful data and a checksum.

A WIF private key is just another way of representing your private key. If you have a WIF private key, you can always convert it back to a raw private key.

Never reveal your WIF private key. A WIF private key is not encrypted in any way, so you need to protect it as much as you would a raw private key.

Benefits

Why do we use WIF private keys?

The main benefit WIF is that it's a Base58 encoding of a private key, so it's shorter and easier to copy.

There are a few other benefits:

  • Identification. A WIF private key always starts with a K, L, or 5. This makes them somewhat easier to identify as private keys as opposed to random-looking 32-byte hexadecimal strings. Personally I think this is the most useful benefit of converting a private key to WIF.
  • Compression Byte. A WIF private key contains a byte that indicates whether the private key is being used to create a compressed or uncompressed public key. So when you import the WIF private key in to a wallet, the wallet can scan the blockchain to look for coins locked to one address, rather than having to scan for a choice of two possible addresses. This is not hugely useful as almost everyone uses compressed public keys anyway, and it wouldn't take too long to scan the blockchain for two types of public keys/addresses, but it's helpful somewhat.
  • Checksum. A WIF private key also contains a checksum, which means that you can easily detect if it has been entered incorrectly when importing in to a wallet. It's not going to help you fix anything if you've written it down incorrectly in the first place, but it's a minor convenience.

Encoding

Convert a private key to WIF

Converting a raw private key to WIF is fairly straightforward:

  1. Start with a 32-byte hexadecimal private key.
  2. Add a version byte to the start. This indicates whether the private key is being used on mainnet or testnet:
    • 80 = mainnet
    • ef = testnet
  3. Add a compression byte to the end (optional). This indicates whether the private key is being used to create a compressed or uncompressed public key:
    • 01 = compressed public key (most common)
    • (no byte) = uncompressed public key
  4. Create a checksum from the above data and add it to the end.
    • A checksum in Bitcoin is the first 4 bytes of the Hash256 of some data.
  5. Convert all of the above data to Base58.

And there you have a WIF private key.

Code

# ---------# Functions# ---------require 'digest'# hash256 function (checksums use hash256)def hash256(hex) binary = [hex].pack("H*") hash1 = Digest::SHA256.digest(binary) hash2 = Digest::SHA256.digest(hash1) result = hash2.unpack("H*")[0] return resultend# checksum functiondef checksum(hex) hash = hash256(hex) # Hash the data through SHA256 twice return hash[0...8] # Return the first 4 bytes (8 characters)end# base58 encode functiondef base58_encode(hex) chars = %w[ 1 2 3 4 5 6 7 8 9 A B C D E F G H J K L M N P Q R S T U V W X Y Z a b c d e f g h i j k m n o p q r s t u v w x y z] base = chars.length i = hex.to_i(16) buffer = String.new while i > 0 remainder = i % base i = i / base buffer = chars[remainder] + buffer end # add '1's to the start based on number of leading bytes of zeros leading_zero_bytes = (hex.match(/^([0]+)/) ? $1 : '').size / 2 ("1"*leading_zero_bytes) + bufferend# ----------# WIF Encode# ----------# 1. start with a 32-byte hexadecimal private keyprivatekey = "ef235aacf90d9f4aadd8c92e4b2562e1d9eb97f0df9ba3b508258739cb013db2" # example, do not use# 2. add prefix (80 = mainet, ef = testnet)data = "80" + privatekey# 3. add compression byte (optional)data = data + "01"# 4. add checksumdata = data + checksum(data)# 5. base58 encodewif = base58_encode(data)# resultputs wif #=> L5EZftvrYaSudiozVRzTqLcHLNDoVn7H5HSfM9BAN6tMJX8oTWz6
import hashlib # SHA-256 hash function# 1. start with a 32-byte hexadecimal private keyprivatekey = "ef235aacf90d9f4aadd8c92e4b2562e1d9eb97f0df9ba3b508258739cb013db2" # example, do not use# 2. add prefix (80 = mainet, ef = testnet)data = "80" + privatekey# 3. add compression byte (optional)data = data + "01"# 4. add checksum (hash256 the prefix+data+checksum, then take the first 4 bytes)hash1 = hashlib.sha256(bytes.fromhex(data)).digest() # convert hex string to raw bytes before hashinghash2 = hashlib.sha256(hash1).hexdigest() # return result as hex stringchecksum = hash2[0:8] # checksum is the first 4 bytesdata = data + checksum # add checksum to the end of the data# 5. set base58 characterscharacters = ['1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']# 6. convert hex data to integer so we can convert it to base58i = int(data, 16)# 7. create a buffer for holding the base58 stringbase58 = ''# 8. keep dividing the integer by 58 and taking the remainder to work out each base58 characterwhile i > 0: i, remainder = divmod(i, 58) # divide and get the remainder base58 = characters[remainder] + base58 # use the remainder to get the character, and add it to the start of the string# note: during normal base58 encoding you convert leading 00 bytes in hex to 1s in base58, but leading zero bytes will not be present when creating a wif private key so we're skipping that step here# 9. show result (wif private key)print(base58) #=> L5EZftvrYaSudiozVRzTqLcHLNDoVn7H5HSfM9BAN6tMJX8oTWz6
  • On mainnet, a WIF should start with a K, L, or 5.
  • On testnet, a WIF should start with a c or a 9.

Decoding

Convert from WIF to a private key

It's easy enough to extract a raw private key from WIF:

  1. Start with the 51 or 52 character WIF private key.
  2. Decode it from Base58.
    • This will give you 37 or 38 hexadecimal bytes.
  3. The private key is contained within bytes 1-33 (i.e. ignore the first 2 characters, then take the next 64 characters).

You can also extract the extra data from the WIF private key (if you need to):

  • The first byte is the version byte, which is used to determine if the private key is meant to be used on mainnet or testnet.
    • 80 = mainnet
    • ef = testnet
  • The optional byte after the private key is the compression byte, which is used to determine if the private key was used to create a compressed or uncompressed public key. If it's not there (i.e. you've only got 37 bytes after decoding from Base58), then it indicates an uncompressed public key.
    • 01 = compressed public key (most common)
    • (no byte) = uncompressed public key
  • The last 4 bytes is the checksum, which allows you to check if the WIF is valid or not

Code

# ---------# Functions# ---------# base58 decode functiondef base58_decode(base58_string) # base58 characters base58_chars = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" # set starting integer value integer = 0 # run through each character in the string from right to left base58_string.reverse.each_char.with_index do |char, index| # get the position of the character in the list of base58 characters char_index = base58_chars.index(char) # check its a valid base58 character if !char_index puts "Not a valid Base58 character: #{char}" exit end # multiply the position of the character by a power of 58 (increasing for the index of each character) integer += char_index * (58**index) end # convert the integer to a hexadecimal string hexadecimal = integer.to_s(16) # pad out to make sure it's an even number of bytes if hexadecimal.bytesize.odd? hexdecimal = "0" + hexadecimal end # ignore empty base58 strings if hexadecimal == "00" hexadecimal = "" end # count the number of leading 1's leading_zero_bytes = (base58_string.match(/^([1]+)/) ? $1 : '').size # convert leading 1's to leading 00's if leading_zero_bytes > 0 hexadecimal = ("00" * leading_zero_bytes) + hexadecimal end # return hexadecimal bytes return hexadecimalend# ----------# WIF Decode# ----------# 1. start with a wif private keywif = "L5EZftvrYaSudiozVRzTqLcHLNDoVn7H5HSfM9BAN6tMJX8oTWz6" # example, do not use# 2. base58 decodedata = base58_decode(wif)# 3. extract the private key (bytes 1 to 33)privatekey = data[2...66]# resultputs privatekey #=> ef235aacf90d9f4aadd8c92e4b2562e1d9eb97f0df9ba3b508258739cb013db2
# 1. start with a wif private keywif = "L5EZftvrYaSudiozVRzTqLcHLNDoVn7H5HSfM9BAN6tMJX8oTWz6" # example, do not use# 2. set base58 characterscharacters = ['1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']# 3. convert base58 string to integer# 3a. reverse the base58 string so we can work from right to leftwif = wif[::-1]# 3b. set starting valuesum = 0# 3c. run through each character in the wif private key (the base58 string)for i, c in enumerate(wif): # 3d. get the index number of this character from the list of base58 characters for index, base58_character in enumerate(characters): # this is a basic way to find the key from the list, but it works if (c == base58_character): character_index = index break # stop looking # 3e. multiply the index of the character by a power of 58 (increasing the power based on the position of the character in the base58 string), then add this to the sum sum += character_index * (58**i)# 4. convert integer to a hexadecimalhexadecimal = hex(sum)[2:] # remove the 0x prefix using [2:]# note: during normal base58 decoding you convert leading 1s in base58 to leading 00 bytes in hex, but wif private keys never start with a 1 so we're skipping that step here# 5. extract the private key (ignore the prefix, compression byte, and checksum)privatekey = hexadecimal[2:66]# 6. pad out the private key so it always shows as 32 bytes (64 hexadecimal characters)privatekey = privatekey.zfill(64) # zfill pads with zeros at the start to the desired length# 6. show resultprint(privatekey) #=> ef235aacf90d9f4aadd8c92e4b2562e1d9eb97f0df9ba3b508258739cb013db2

Usage

Where are WIF private keys used in Bitcoin?

As mentioned, WIF is used when you're exporting or importing private keys between wallets.

Some examples of popular wallets that use WIF are:

From my experience it's more common for wallets to require you to work with WIF private keys as opposed to allowing you to import/export raw private keys.

History

When were WIF private keys introduced in Bitcoin?

Pieter Wuille created the WIF format in 2011 for importing and exporting private keys via Bitcoin Core.

https://github.com/bitcoin/bitcoin/pull/574

Thanks to Murch and Ava Chow for the help with the origin of WIF private keys.

Summary

WIF is just designed to be a more user-friendly encoding of a private key.

You can spot a WIF private key because it's a Base58 string and starts with a K or L. On the odd occasion it will start with a 5 (if you're working with uncompressed public keys for some reason). For example:

These are static examples of WIF private keys. Do not use them.

  • Ky1BY5QkB6xb3iQQjJQmVcvqc6mkLBaZTW1xCWpf91aFGBh1kyQ7 (for a compressed public key on mainnet)
  • L1Rw26ZuhBqguYDSi77zAxyfHUZ2H1JAQunf3TEbxyfcBDjUvBse (for a compressed public key on mainnet)
  • 5JKZUnxc5G8toCqErCQpHiUYff3t7GvBd2my4bf6odejtZAy7hG (for an uncompressed public key on mainnet)

So if you're working on mainnet with compressed public keys like a normal person, look for the K or L at the start.

From my experience it can be a bit annoying to have to convert between raw private key and WIF when you want to import a private key in to a wallet, but it's common practice for wallets to work with WIF instead of raw private keys, so you might as well get used to it.

If you're working with raw private keys locally (and occasionally want to import/export them), it's a good idea to write your own WIF encoder/decoder. The last thing you want to do is trust a website or tool to handle your private keys, and it's not hard to create a tool that converts between WIF and a raw private key yourself.

It will save time and stress later on. Trust me.

Because as that famous old saying goes, "Not Your Own WIF Tool, Not Your Coins".

Or something like that.

Resources

Tools

  • WIF Decode, WIF Encode — Handy command-line tools for converting between a hex private key and WIF on your local computer.
WIF Private Key | Wallet Import Format (2024)

FAQs

What is the WIF format for private key? ›

A WIF (Wallet Import Format) private key is an address-style format for a private key. It's used when exporting and importing private keys between bitcoin wallets. It's mainly a Base58 encoding of the private key, but also includes some extra useful data and a checksum.

What is the format of a Bitcoin private key? ›

Bitcoin private keys can be represented in various formats, including: Hexadecimal: A string of numbers and letters. Wallet Import Format (WIF): A more user-friendly format starting with '5', 'K', or 'L'. Mnemonic Phrase: A sequence of words that can be used to regenerate the private key.

What does import private key mean? ›

The process of importing your private key means you are essentially recreating your wallet on a new device or platform without paying any extra fees. Your keys don't “move” from one wallet to another, just replicated on your new wallet platform.

How do I import wallet with private key? ›

From the wallet view, tap the currently selected account to bring up the account selector. Tap 'Add account or hardware wallet' at the bottom of the menu. Hit 'Import account'. On this screen, paste in the private key of the account you want to import, or scan a QR code if supported by the other wallet.

What format should a private key be in? ›

Single file (private key with certificates) format

PEM-encoded. This file can contain the private key and the primary certificate, or the private key and the chain of certificates combined in the following order: Private key and primary certificate. Private key, primary certificate, and intermediate certificate.

How does the private key look like? ›

Generally, they are 256 digits long, but for simplicity, private keys are usually expressed in hexadecimal form. While hashing a public address from a private key is trivial, the reverse is almost impossible. Modern hardware and software are not capable of cracking encrypted keys.

How many digits is a Bitcoin private key? ›

A private key is a 256-bit number. This means that it is represented in binary in 256 numbers of 0 or 1.

What is an example of a private key in a Bitcoin wallet? ›

An example private key

In Bitcoin, a private key is a 256-bit number, which can be represented one of several ways. Here is a private key in hexadecimal - 256 bits in hexadecimal is 32 bytes, or 64 characters in the range 0-9 or A-F.

Which BTC wallet can import private keys? ›

Electrum is a widely used Bitcoin wallet that provides the ability to import private keys. It's a lightweight wallet with a focus on security and user control. Remember to exercise caution when importing private keys into any wallet, as mishandling them can lead to potential security risks.

How to restore Bitcoin wallet with private key? ›

Private keys can also be used to restore access to your Bitcoin:
  1. Download a Wallet App: Choose a wallet app that allows importing private keys.
  2. Open the App and Select Import: Find the option to import or restore a wallet.
  3. Enter the Private Key: Input your private key when prompted.
Jun 18, 2024

What permissions should my private key have? ›

For this reason, SSH requires private keys to be accessible only to the current user. The current permissions on the key, 0777 , mean that it is readable, writeable, and executable by the current user, members of that user's group, and members outside that user's group.

What is the format of wallet private key? ›

Private keys are what are used to unlock satoshis from a particular address. In Bitcoin, a private key in standard format is simply a 256-bit number, between the values: 0x01 and 0xFFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFE BAAE DCE6 AF48 A03B BFD2 5E8C D036 4140, representing nearly the entire range of 2256-1 values.

How to import BTC private key to trust wallet? ›

Access Wallet Import Screen

In the Settings screen, you will find here Wallets. Tap on the “+” sign on the upper right then choose Add existing wallet. Select the network, in this example – Ethereum. Choose Private key and paste in your private key.

Where can I import a private key? ›

Yes, you can import a private key into another wallet using the Trust Wallet app. Open Trust Wallet, go to Settings, choose "Wallets," and tap on "Add Wallet." Select "Import Wallet," enter the private key, and tap "Import." Your wallet will be accessible on Trust Wallet after this process.

What is a private key example? ›

Private key encryption is often used to encrypt data stored or transmitted between two parties. For example, when you log in to a website using a username and password, the password is often encrypted using a private key before it is transmitted to the web server.

What is the format of a private key pkcs12? ›

In cryptography, PKCS #12 defines an archive file format for storing many cryptography objects as a single file. It is commonly used to bundle a private key with its X. 509 certificate or to bundle all the members of a chain of trust.

What is plaintext private key? ›

A plaintext private key is an unencrypted private key. Ownership of the private key means ownership and control of the assets in your wallet.

What is private key file format PEM or PPK? ›

pem are two commonly used file formats for storing public and private keys for secure communication. While . ppk files are specific to PuTTY and use a proprietary format, . pem files use the widely used ASCII text format and can be used to store various types of keys.

Top Articles
Singapore
The Truth About Energy Drinks
Warren Ohio Craigslist
Fat Hog Prices Today
Cars & Trucks - By Owner near Kissimmee, FL - craigslist
Regal Amc Near Me
What to Do For Dog Upset Stomach
Falgout Funeral Home Obituaries Houma
Konkurrenz für Kioske: 7-Eleven will Minisupermärkte in Deutschland etablieren
Craigslist Vermillion South Dakota
How to Type German letters ä, ö, ü and the ß on your Keyboard
Hallowed Sepulchre Instances & More
Optum Medicare Support
LeBron James comes out on fire, scores first 16 points for Cavaliers in Game 2 vs. Pacers
Regular Clear vs Low Iron Glass for Shower Doors
The Rise of Breckie Hill: How She Became a Social Media Star | Entertainment
REVIEW - Empire of Sin
The Shoppes At Zion Directory
Nyuonsite
Maplestar Kemono
Bnsf.com/Workforce Hub
Lake Nockamixon Fishing Report
Apple Original Films and Skydance Animation’s highly anticipated “Luck” to premiere globally on Apple TV+ on Friday, August 5
Theater X Orange Heights Florida
Reborn Rich Kissasian
Okc Body Rub
Unable to receive sms verification codes
Is Poke Healthy? Benefits, Risks, and Tips
Elijah Streams Videos
J&R Cycle Villa Park
Jt Closeout World Rushville Indiana
Baddies Only .Tv
Wake County Court Records | NorthCarolinaCourtRecords.us
404-459-1280
How to Play the G Chord on Guitar: A Comprehensive Guide - Breakthrough Guitar | Online Guitar Lessons
Covalen hiring Ai Annotator - Dutch , Finnish, Japanese , Polish , Swedish in Dublin, County Dublin, Ireland | LinkedIn
Western Gold Gateway
Dr. John Mathews Jr., MD – Fairfax, VA | Internal Medicine on Doximity
Gym Assistant Manager Salary
Bill Manser Net Worth
Academic Notice and Subject to Dismissal
Nearest Wintrust Bank
60 Days From August 16
German American Bank Owenton Ky
Motorcycle For Sale In Deep East Texas By Owner
Model Center Jasmin
SF bay area cars & trucks "chevrolet 50" - craigslist
Nfl Espn Expert Picks 2023
Ocean County Mugshots
Worlds Hardest Game Tyrone
Scholar Dollar Nmsu
Sunset On November 5 2023
Latest Posts
Article information

Author: Maia Crooks Jr

Last Updated:

Views: 5776

Rating: 4.2 / 5 (43 voted)

Reviews: 82% of readers found this page helpful

Author information

Name: Maia Crooks Jr

Birthday: 1997-09-21

Address: 93119 Joseph Street, Peggyfurt, NC 11582

Phone: +2983088926881

Job: Principal Design Liaison

Hobby: Web surfing, Skiing, role-playing games, Sketching, Polo, Sewing, Genealogy

Introduction: My name is Maia Crooks Jr, I am a homely, joyous, shiny, successful, hilarious, thoughtful, joyous person who loves writing and wants to share my knowledge and understanding with you.