Private key → uncompressed public key
Compute P = k·G on secp256k1 and serialize the point in the original 65-byte form 04‖X‖Y — the encoding every key generated before 2012 used, and the only one that reproduces an old uncompressed address or a 5… WIF.
Enter a value above and press Convert. Not sure what to type? Press “Use example” to load the sample from the placeholder.
What this page computes
You give it a 256-bit private key k and it produces the
uncompressed public key: the elliptic-curve point P = k·G written out in full,
both coordinates, tagged with a single 04 byte. That is 65 bytes — the format Satoshi's original
client used for every key it ever made.
Nothing here is a new kind of cryptography. The curve arithmetic is identical to the compressed-key page; only the serialization of the resulting point differs — and that difference is what gives one private key two unrelated addresses.
1. Why the uncompressed form is exactly 65 bytes
A public key is a point on secp256k1: two numbers X and Y in the range
[0, p−1] satisfying Y² ≡ X³ + 7 (mod p), with
p = 0xFFFFFFFF…FFFFFC2F (256 bits). Since each coordinate is smaller than p, each one
fits into 32 bytes. The encoding is the obvious one — a one-byte tag saying "here comes a point
in uncompressed form", then the two coordinates:
| Offset (bytes) | Length | Field | Value for this page's purpose |
|---|---|---|---|
| 0 | 1 | Type tag / prefix | 04 = uncompressed point |
| 1 | 32 | X coordinate, big-endian, zero-padded | first coordinate of P = k·G |
| 33 | 32 | Y coordinate, big-endian, zero-padded | second coordinate of P |
| 65 bytes total | 520 bits → 130 hex digits | ||
Three details are easy to get wrong:
- The coordinates are fixed-width. Unlike DER-encoded integers (which drop leading zero
bytes), a SEC1 coordinate is always 32 bytes. If
Xhappened to be0x00a1…, that leading00byte stays. Removing it would shift every following byte and produce a key of a different length — which is exactly what some broken parsers used to do. - Big-endian. The first byte after the tag is the most significant byte of
X. Key serialization is never little-endian, unlike some other Bitcoin structures. - The
04byte is not part of the number. It is a tag, exactly like the02/03tag of the compressed form. Hash the 65 bytes as a unit; the tag participates in the hash.
2. The prefix byte: 04, and the abandoned 06/07
The first byte comes from SEC1, the standard that defines how elliptic-curve points are written as octet strings. SEC1 gives each point encoding a one-byte identifier, and Bitcoin inherited all of them:
| Prefix | Name | Layout | Length | Status today |
|---|---|---|---|---|
00 | Point at infinity | — | 1 byte | Never valid as a public key; k = 0 cannot produce it |
02 | Compressed, even Y | 02 ‖ X | 33 bytes | Standard modern form |
03 | Compressed, odd Y | 03 ‖ X | 33 bytes | Standard modern form |
04 | Uncompressed | 04 ‖ X ‖ Y | 65 bytes | Legacy but fully valid in legacy scripts |
06 | Hybrid, even Y | 06 ‖ X ‖ Y | 65 bytes | Obsolete; redundant parity bit |
07 | Hybrid, odd Y | 07 ‖ X ‖ Y | 65 bytes | Obsolete; redundant parity bit |
| none | x-only (BIP340 / Taproot) | X | 32 bytes | Modern for Taproot only |
The hybrid forms 06 and 07 carried the parity of Y
in the low bit of the tag (06 = even, 07 = odd) and also wrote out
Y in full. The parity bit therefore said nothing the Y bytes did not already say,
while handing an attacker a second, redundant field to tamper with: flip the tag and the key becomes internally
inconsistent. Later revisions of SEC1 dropped the hybrid encodings for exactly that reason, no wallet ever
emitted them, and they carry no meaningful transaction volume. This page's shared parser still accepts a
06/07 key so you can inspect one — never generate or store one.
The 04 here is a point tag. It is unrelated to the version byte of an address
(0x00 for mainnet P2PKH) or the version byte of a WIF (0x80). Three different
"prefix bytes" appear in one derivation chain; conflating them is a classic beginner error.
3. Where this format came from — and why it changed in 2012
The original Bitcoin client (2009) generated keys through OpenSSL. OpenSSL's default octet-string encoding
for an EC point is the uncompressed one, so every key created by the first three years of Bitcoin
software was a 65-byte 04‖X‖Y key, and every address in the early blockchain was
hash160 of that 65-byte string. That is the historical default, not a special "legacy mode"
someone switched on.
Compression was proposed later as a space optimization. A point's Y coordinate is fully
determined by X plus one bit (its parity), so 32 of the 65 bytes are redundant. A BIP-style
proposal worked through the change, and Bitcoin 0.6.0, released in March 2012, shipped support
for compressed public keys and made them the default for newly generated keys. The motivations were purely
economic and practical:
- Every spend from a P2PKH output embeds the public key in the scriptSig. A 33-byte key instead of 65 saves 32 bytes per input — a ~23 % smaller scriptSig, and real money at scale.
- Smaller inputs mean a smaller UTXO set and a smaller blockchain — a live concern even in 2012.
- Security is identical: both encodings describe the same point, and ECDSA does not care how the point was written down.
Because the change altered the bytes that get hashed, wallets had to tell their users which form a key was
in — a raw private key carries no such information. That is the entire reason the WIF format grew a
0x01 compression flag in the same release (see private key → compressed
WIF). Crucially, the change added a format; it did not invalidate the old one. Coins sitting at
uncompressed addresses in 2012 are still spendable today, by the same consensus rules.
4. Why the uncompressed form still matters
- Old funds. Any key or address generated before mid-2012, and any created afterwards by
software that never adopted compression, holds its coins at
hash160(04‖X‖Y). Recovering such coins requires reproducing exactly that 65-byte string. - Paper wallets. Printed wallets from the 2011–2013 era, and many physical-bitcoin
collectibles of the same period, were built with uncompressed keys. Their private key is printed as a
5…WIF precisely because the pairing is uncompressed key + uncompressed address. - Sweeping. To spend from such an address, the scriptSig must push the public key whose hash160 matches the one committed in the address. Push the compressed key instead and the P2PKH check fails — the transaction is rejected, not silently redirected.
- Forensics and recovery. Given an address and a candidate key, you need both serializations to decide which one the address belongs to — literally what this page computes.
SegWit witness-v0 rules require a compressed public key: P2WPKH and P2SH-P2WPKH outputs can only be spent
with a 33-byte key. The same goes for any modern descriptor-based wallet that refuses uncompressed keys at
import time. So an uncompressed key leads to P2PKH (and historical bare-P2PK) scripts only —
you cannot turn it into a bc1q… address.
5. Worked example with the real demo values
Everything in this table is what this page computes for the sample key shown in the input box. You can reproduce it by pressing "Use example":
| Step | Value |
|---|---|
Private key k (hex) | 0824c314772b2c2859c889471390a36bf66e53a1ca1642f96f0f2c9307a171ca |
| Private key (decimal) | 3683455675284633286911943861444039993120875154046227415438637967083965608394 |
X of P = k·G | ff812e26116a9aa140abe629e7f8a38401653caf925119def59ed3758c67ee80 |
Y of P | 8f49cde13c7ffd64f1d730bf87a743a578eda4971ddac4a08118160732b424ae |
| Parity of Y | last hex digit e → even (so the compressed sibling of this key starts with 02) |
| Uncompressed public key (this page's output) | 04ff812e26116a9aa140abe629e7f8a38401653caf925119def59ed3758c67ee808f49cde13c7ffd64f1d730bf87a743a578eda4971ddac4a08118160732b424ae |
| Its length | 65 bytes = 130 hex digits = 520 bits |
| hash160 of that 65-byte string | 3f0e966dc089c611a9c1d03bd4f69ea53b0223f9 |
| P2PKH address from it | 16kR3eiswUY6tmGnxZhwQmW6LAvTLGWG2G |
| For contrast: compressed key | 02ff812e26116a9aa140abe629e7f8a38401653caf925119def59ed3758c67ee80 |
| For contrast: its hash160 | 21f57b6debcfc5b67182dfb4af1641f0a8189012 |
| For contrast: its P2PKH address | 146ZNjH7XTXnMd1ofe3z7CL2i8WM7N2UqT |
The last three rows are the whole point of this page. The same 256-bit number k is responsible
for both 16kR3eis…GWG2G and 146ZNjH7…2UqT. They are not aliases: they are
two distinct 20-byte commitments, two distinct addresses, and a wallet normally watches only one of them.
The address itself is a Base58Check structure built from the hash160 above:
| Address part | Length | Demo value |
|---|---|---|
| Version byte | 1 byte | 00 |
| hash160 payload | 20 bytes | 3f0e966dc089c611a9c1d03bd4f69ea53b0223f9 |
| Checksum = first 4 bytes of SHA256d(payload) | 4 bytes | 3b0b7cbd |
| Encoded result | 34 characters of Base58 | 16kR3eiswUY6tmGnxZhwQmW6LAvTLGWG2G |
6. Compressed vs uncompressed, side by side
| Uncompressed | Compressed | |
|---|---|---|
| Serialization | 04 ‖ X ‖ Y | 02/03 ‖ X |
| Bytes / hex digits / bits | 65 / 130 / 520 | 33 / 66 / 264 |
| Information carried | Both coordinates | X plus the parity of Y |
| hash160 input | all 65 bytes | all 33 bytes |
| P2PKH address (same key) | 16kR3eis…GWG2G | 146ZNjH7…2UqT |
| Matching WIF prefix | 5… | K… / L… |
| Public key bytes pushed when spending | 65 | 33 |
| Typical P2PKH scriptSig size | 1 + 72 + 1 + 65 = 139 bytes | 1 + 72 + 1 + 33 = 107 bytes |
| Usable in witness v0 / Taproot | No | Witness v0 yes (x-only key for Taproot) |
| Default since | Bitcoin 0.1 (2009) | Bitcoin 0.6.0 (March 2012) |
| Still consensus-valid? | Yes, for legacy script types | Yes |
The scriptSig arithmetic is worth spelling out: a P2PKH spend pushes one DER signature plus its 1-byte sighash type (about 72 bytes) and one public key, each preceded by a length byte. At a fee rate expressed in satoshis per virtual byte, that 32-byte difference is paid on every input, forever.
7. One key, two addresses — the most common "I lost my coins" story
The number k is just a number. "Compressed" or "uncompressed" is a property of the
serialization, and the only place that choice is recorded in a wallet backup is one flag byte inside
the WIF string. Import an uncompressed key into a wallet that assumes compression, and it will derive
hash160(02/03‖X), look up 146ZNjH7…, find nothing, and display a zero balance —
while your actual coins sit untouched at 16kR3eis…. Nothing has been lost, but it looks
exactly like a loss, and this is the single most common version of that story.
Three consequences worth remembering:
- Both addresses are spendable by you. The same private key controls the compressed and the uncompressed address. If someone ever paid you at an old address, you can still move those coins.
- They cannot be merged. You cannot "convert" an uncompressed address into a compressed one; you can only send the coins from the former to the latter in an ordinary transaction, paying a fee.
- Check both before concluding anything. When a restored wallet shows zero, compute both forms (this page and its compressed twin do exactly that) and search the blockchain for both addresses.
8. What happens after this step
- Private key → P2PKH uncompressed address — the full address construction, version byte and checksum included.
- Private key → uncompressed WIF — the matching
5…backup string, which is what you would actually import into a wallet. - Private key → compressed public key — the 33-byte sibling and its own addresses.
- Uncompressed public key → hash160 → addresses — the same computation starting from a key you already have, with an on-curve check.
9. Security notes
- Security is not reduced by using 65 bytes. Compressed and uncompressed keys are the same curve point; the discrete-log problem, the signature scheme and the effective key strength are identical. "Uncompressed" means "longer", not "weaker".
- It costs more to spend. A larger scriptSig means a larger transaction and a higher fee for the same economic value transferred. That is the only practical penalty, and it is why no modern wallet hands out uncompressed addresses.
- Validate points you receive. An off-curve
(X, Y)pair can be used for invalid-curve attacks against careless implementations. This site verifiesY² ≡ X³ + 7before using a point. - A private key in a web form is a private key on the wire. This page submits over the request line, and anything that reaches a server may be captured in a log or proxy. Treat this tool as a teaching aid: experiment with throwaway keys, and move real funds only inside software you control.
- Quantum exposure is unchanged. A published public key — compressed or not — is what Shor's algorithm attacks; 32 extra bytes buy no quantum resistance.
10. Common mistakes
- Dropping the
04. The tag is part of the hash160 input. A 64-byte "X‖Y" string hashes to something completely different and is not a valid public key. - Trimming leading zero bytes from a coordinate. Fixed width is mandatory: 32 bytes for each coordinate, always.
- Believing compressed and uncompressed are two different keys. They are two serializations of one point, controlled by one private key.
- Expecting an uncompressed key to work in SegWit. Witness v0 requires compression; an uncompressed key simply cannot be used there.
- Assuming the
04tag encodes parity. It does not. Only the hybrid06/07tags and the compressed02/03tags carry parity. - Spending an uncompressed-address UTXO with a compressed key. The script fails; the wallet must present the exact public key that hashes to the address.
11. Quick reference
| Item | Value |
|---|---|
| Formula | P = k·G on secp256k1 |
| Encoding | 0x04 ‖ X(32) ‖ Y(32) |
| Length | 65 bytes / 130 hex digits / 520 bits |
| Prefix meanings | 02/03 compressed, 04 uncompressed, 06/07 hybrid (obsolete) |
| Coordinates | Big-endian, fixed 32 bytes, reduced mod p |
| Where the prefix lives | Inside the hash160 preimage — it changes the address |
| Reachable address types | P2PKH (1…) and legacy bare P2PK only |
| Matching backup format | WIF starting with 5, 51 characters |
Reversible to k? | No (ECDLP) |
| Still valid on-chain? | Yes, for legacy script types |