Private Key Tools

Private key → compressed WIF

Base58Check-encode the payload 0x80 ‖ k ‖ 0x01 and get the 52-character K…/L… Wallet Import Format string that tells a wallet to derive the compressed public key — the modern default, and the format behind every SegWit- and Taproot-capable single-key import.

64 hex digits = 32 bytes. The WIF produced here is exactly what a wallet would export for this key in compressed form. Never paste a mainnet key into a page you do not control.
No input yet

Enter a value above and press Convert. Not sure what to type? Press “Use example” to load the sample from the placeholder.

How it works

What this page computes

You give it a 256-bit private key and it produces the compressed WIF — the Wallet Import Format string that starts with K or L, is 52 characters long, and tells a wallet to derive the compressed public key from that key. WIF is not a new secret and not a new kind of key: it is your private key, plus two bytes of metadata, plus a checksum, written in Base58.

WIFcompressed = Base58Check( 0x80 ‖ k ‖ 0x01 )
private key k (32 B)→ 0x80 ‖ k ‖ 0x01 (34 B)→ SHA-256 twice→ first 4 bytes→ 38 bytes→ Base58→ 52-char WIF

Every part of that chain is shown separately in the result panel above: the payload, each of its fields, the hash, the checksum, and the final string.

1. What Base58 is, and why the alphabet skips 0 O I l

Base58 is positional notation in base 58 — like decimal or hexadecimal, but with a hand-picked alphabet of 58 characters. Encoding a byte string means treating it as one huge integer and repeatedly dividing by 58, collecting remainders; decoding reverses that. The alphabet is case-sensitive and free of punctuation, so a string can be read aloud, typed from a printed page or embedded in a QR code without quoting or escaping.

Alphabet segmentCharactersCountDeliberately absent
Digits1 2 3 4 5 6 7 8 990 (confused with O)
Upper caseA B C D E F G H J K L M N P Q R S T U V W X Y Z24I (confused with 1 and l), O (confused with 0)
Lower casea b c d e f g h i j k m n o p q r s t u v w x y z25l (confused with 1 and I)
Total589 + 24 + 25 = 58

Those four omissions are the entire point of the alphabet. Bitcoin keys and addresses are transcribed by humans — off a screen, a paper backup, a metal plate — and the likeliest transcription error is 0↔O or 1↔I↔l. Deleting the ambiguous glyphs removes a whole class of mistakes instead of merely detecting it later.

2. Why there is a checksum, and exactly how it is computed

Base58 alone has no error detection: change one character and you get a different, perfectly well-formed number — which for a private key means another key, or a string some wallet rejects with a cryptic error. Bitcoin therefore appends four checksum bytes before encoding, a scheme called Base58Check:

checksum = first 4 bytes of SHA256( SHA256( payload ) )

SHA-256 is applied twice (the SHA256d used for block hashes and transaction IDs), truncated to 32 bits, and appended to the payload. On import a wallet recomputes it and compares. For the demo key the whole computation is visible:

StageValue
Payload (34 bytes)800824c314772b2c2859c889471390a36bf66e53a1ca1642f96f0f2c9307a171ca01
SHA256(payload)b6020359be4735a8dafe0d76b886c0de8a09ea9459aeba16cb3e3b5473b5d0c2
SHA256(SHA256(payload))3a0a0417ffa98881ccdd0c7b283639584e0e909389f6bfbbdbac54547d2b732d
Checksum (first 4 bytes)3a0a0417
Final 38 bytes fed to Base58800824c314772b2c2859c889471390a36bf66e53a1ca1642f96f0f2c9307a171ca013a0a0417

The checksum is only 32 bits, so a random corruption slips through with probability 2−32 ≈ 1 in 4.29 billion — long enough to kill typos, short enough to cost four bytes. Change one character of the demo WIF and this page's decoder answers "WIF checksum is invalid (typo or truncated string)" instead of silently returning a different key.

A checksum is not a signature

Base58Check protects you from accidents, not from adversaries. Anyone who learns your private key can compute a valid checksum for any WIF they like — there is no authentication and no key material in those four bytes.

3. The payload: 33 bytes of data, 34 with the flag

WIF is defined as a Base58Check encoding of a payload that begins with a version byte. For a compressed key the payload is 34 bytes long, and each byte has a job:

Offset (payload)LengthFieldDemo valueMeaning
01 byteVersion byte80Mainnet private key (0x80 = 128)
1 – 3232 bytesThe private key itself0824c31477…07a171caBig-endian scalar, zero-padded to 32 bytes
331 byteCompression flag01"Derive the compressed public key from this key"
34 – 374 bytesChecksum3a0a0417First 4 bytes of SHA256d(bytes 0–33)
38 bytes34 bytes of payload + 4 bytes of checksum → 52 Base58 characters

The version byte identifies the coin and the key type, and it is what makes the resulting string recognisable at a glance:

Version byteNetwork / useResulting WIF starts withPayload length
0x80 (128)Bitcoin mainnet, uncompressed533 bytes
0x80 (128)Bitcoin mainnet, compressedK or L34 bytes
0xef (239)Bitcoin testnet, uncompressed933 bytes
0xef (239)Bitcoin testnet, compressedc34 bytes
0x00 (0)Not a WIF — P2PKH address version1 (address)21 bytes
0x05 (5)Not a WIF — P2SH address version3 (address)21 bytes

Notice the last two rows: 0x00 and 0x05 are address version bytes, not key version bytes. Three version-like bytes appear across one derivation chain — 0x04 the SEC1 point tag, 0x80 the WIF version, 0x00 the P2PKH version — and mixing them up is a classic confusion.

4. Why compressed WIFs are 52 characters and start with K or L

Base58 is a big-integer encoding, so the length of the output is set by the size of the number: each Base58 character carries log258 ≈ 5.858 bits. A 38-byte value is 304 bits, and 304 / 5.858 ≈ 51.9, so at most 52 characters are needed. A 37-byte value is 296 bits and 296 / 5.858 ≈ 50.5, giving at most 51 characters. That single byte — the compression flag — is exactly what moves the WIF from 51 to 52 characters.

The first character is a stronger statement. The first Base58 digit is floor(value / 5851), and a mainnet compressed WIF always begins with the byte 0x80, so its value lies in [2303, 2303 + 2296). With 5851 ≈ 2298.757 the quotient is always between ≈ 18.93 and ≈ 19.08, which can only floor to 18 or 19 — the alphabet positions of K and L. For an uncompressed mainnet WIF the value lies in [2295, 2295 + 2288) and 5850 ≈ 2292.899, giving a quotient between ≈ 4.29 and ≈ 4.32 that always floors to 4 — the character 5. The leading character is not a convention; it is forced by the arithmetic.

FormPayloadTotal encoded bytesBase58 charactersFirst characterDemo value
Compressed (mainnet)34 B38 B = 304 bits52K or LKwVYL77L…GK5tVqG
Uncompressed (mainnet)33 B37 B = 296 bits515 (always)5HssbguBn…aVNekU

A random sample of 400 freshly generated keys on this server produced 184 WIFs starting with K and 216 starting with L, all 52 characters long; 300 uncompressed WIFs from the same keys were all 51 characters and all began with 5. The K/L split is essentially a coin flip, because it depends on the high bits of the random key.

5. Why the 0x01 flag lives inside the WIF

When compressed keys were introduced in 2012 (see the uncompressed key page for the history), wallets had a problem: a backup of a private key was a single string, and the wallet had to know which public-key serialization to derive. A separate field would have broken every existing parser, printed paper wallet and QR code. Instead the payload grew by one optional trailing byte:

One key, two WIFs, two addresses

The same private key has two valid WIF strings: KwVYL77L… (compressed) and 5HssbguBn… (uncompressed) for the demo key. They decode to identical 32-byte keys and different addresses. Neither is "wrong"; they simply describe different derivations. Back up the one that matches where your coins actually are.

6. How a wallet uses the flag to decide which address to spend from

WIF string→ Base58Check decode→ verify checksum→ read version byte (network)→ read payload length / 0x01 flag→ derive pubkey (33 B or 65 B)→ hash160 → P2PKH address→ watch & spend

That branch is the whole point. The flag does not merely affect how the wallet prints your key; it changes the 20-byte hash the wallet watches on-chain and the public key it pushes when spending. With the flag it derives hash160(02/03‖X) and pays to 146ZNjH7…; without it, hash160(04‖X‖Y) and 16kR3eis…. Both are correct addresses for the same key — just different ones.

Importing a compressed WIF into a wallet that expects uncompressed keys

This is the classic failure. Old software either rejects the string — "invalid WIF", "wrong length" — or accepts it and derives the uncompressed address anyway. If your coins are at the compressed address you see a zero balance; if you then send coins to the address it displays, your funds are split across two addresses that two wallets may disagree about. Nothing is cryptographically lost — one key still controls both — but you now need the right tool for each balance. Before trusting an import, check that the address the wallet shows is the address you expected.

7. Worked example — every value computed and verified

All of the following are the real outputs for the sample key in the input box:

ItemValue
Private key k0824c314772b2c2859c889471390a36bf66e53a1ca1642f96f0f2c9307a171ca
Payload 0x80 ‖ k ‖ 0x01800824c314772b2c2859c889471390a36bf66e53a1ca1642f96f0f2c9307a171ca01 (34 bytes)
Checksum3a0a0417
Compressed WIFKwVYL77Lcs1ckM39NvGjrtfKhU4KKdR2iB9Wq2FSMN6rbGK5tVqG
Length / first character52 characters, begins with K
Payload 0x80 ‖ k800824c314772b2c2859c889471390a36bf66e53a1ca1642f96f0f2c9307a171ca (33 bytes)
Uncompressed-checksumb6f3d7f5
Uncompressed WIF (contrast)5HssbguBnjbaUVZCsH9YuzUG7T4vYQf51iiodi4izdVy6aVNekU
Length / first character51 characters, begins with 5
Compressed public key implied02ff812e26116a9aa140abe629e7f8a38401653caf925119def59ed3758c67ee80
hash160 of it21f57b6debcfc5b67182dfb4af1641f0a8189012
P2PKH address implied146ZNjH7XTXnMd1ofe3z7CL2i8WM7N2UqT
Testnet compressed WIF of the same keycMrXo27C3vhsunWQmL5sEDAPKhMiz5WinDHywShwrUkrr1RkCJ4i

Note the checksum difference between the two forms: 3a0a0417 versus b6f3d7f5. Appending the flag byte changes the hash input, so it changes the checksum and the last four characters of the two strings are unrelated — a useful sanity check when comparing two WIFs of the same key by eye.

8. Round-trip verification

An encoding that cannot be decoded is worthless, so this page decodes its own output with Btc::wifDecode() and shows every field it recovers in the result panel: the identical 32-byte key, the compression flag set, version byte 80, network mainnet, a valid checksum, and the 34-byte payload that went in. Base58Check is a bijection, so the round trip must return the original bytes. If a tool decodes your WIF to a different key, the string was mistyped or the tool is broken — there is no third possibility.

9. Compressed vs uncompressed WIF, side by side

Compressed WIFUncompressed WIF
Payload0x80 ‖ k ‖ 0x01 (34 B)0x80 ‖ k (33 B)
Total bytes encoded38 B37 B
String length52 characters51 characters
First character (mainnet)K or L5
First character (testnet)c9
Checksum (demo key)3a0a0417b6f3d7f5
Public key implied33 bytes, 02/03‖X65 bytes, 04‖X‖Y
Address implied (demo key)146ZNjH7…2UqT16kR3eis…WG2G
Usable for SegWit / TaprootYesNo
Fee to spend fromAbout 107-byte scriptSigAbout 139-byte scriptSig
Typical originEvery wallet since 2012Paper wallets and pre-2012 software

See private key → uncompressed WIF for the mirror-image page and WIF → private key HEX for the decoder that tells you which form a string you were given actually is.

10. Security notes

11. Common mistakes

12. Quick reference

ItemValue
EncodingBase58Check: payload ‖ first 4 bytes of SHA256d(payload)
Compressed payload0x80 ‖ k(32 B) ‖ 0x01
Payload / encoded length34 B / 38 B
Output length52 Base58 characters
First character (mainnet compressed)K or L
Checksum size / strength4 bytes / catches all single-character typos in practice (1 in 232 escapes)
Base58 alphabet size58 (no 0, O, I, l)
Flag meaningDerive the 33-byte compressed public key
Address impliedP2PKH from hash160(02/03‖X)
Reversible?Yes — decoding recovers k exactly