Uncompressed public key → hash160 → addresses
Parse a 65-byte 04‖X‖Y public key, prove it really lies on secp256k1, hash it, and build the legacy P2PKH address — then compare it against the compressed serialization of the same point, which produces a completely different address.
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
Input: a 65-byte uncompressed public key — 130 hex digits starting with 04. Output: the parsed
coordinates, a real on-curve verification, the hash160, the legacy P2PKH address, and — side by side — the
compressed serialization of the same point with the different address it produces.
And the contrast path, which only changes the first byte and the length:
1. The 04 ‖ X ‖ Y layout
A public key is not a number you can look up; it is a point on the secp256k1 curve, and the SEC1 standard says how to write a point down. The long form writes both coordinates in full, big-endian, after a one-byte tag:
| Field | Bytes | Hex digits | Content |
|---|---|---|---|
| Prefix | 0 | 0–1 | 04 — "an uncompressed point follows" |
| X | 1–32 | 2–65 | the x coordinate, 32 bytes, big-endian |
| Y | 33–64 | 66–129 | the y coordinate, 32 bytes, big-endian |
| Total | 65 | 130 | 520 bits of serialized point |
Big-endian means the most significant byte comes first: a leading zero byte in the
serialization is meaningful and must not be stripped. A key whose X starts with 00a3… is a
different point from one whose X starts with a3…, and a parser that trims leading zeros is a
parser that will occasionally send money nowhere.
Every prefix byte in SEC1 is a promise about what follows, and there are more of them than people expect:
| Prefix | Length | Meaning | Status |
|---|---|---|---|
02 | 33 B | compressed: x only, y is even | standard |
03 | 33 B | compressed: x only, y is odd | standard |
04 | 65 B | uncompressed: x and y both written out | standard, legacy |
06 | 65 B | hybrid: x and y, and y is even | deprecated |
07 | 65 B | hybrid: x and y, and y is odd | deprecated |
| (none) | 32 B | x-only, y assumed even (BIP340) | Taproot / Schnorr only |
2. Is the point really on the curve?
A public key is only a point if its coordinates satisfy the curve equation. secp256k1 is defined over the
prime field modulo p, so the test is one modular comparison:
If both sides match, the point is on the curve and the rest of the pipeline may proceed. If they do not match, the input is not a public key at all and every subsequent computation is meaningless: hashing it produces a plausible-looking address that nobody can ever spend from, because no private key corresponds to it.
This page performs the check and refuses off-curve input with a readable error instead of rendering a result. That is not politeness, it is the security boundary:
If a program accepts a point without checking it against the curve equation, an attacker can supply a point that lives on a different curve with a much smaller group order. Multiply the victim's secret scalar by that point and the result only reveals the secret modulo that small order — but repeat it with several small orders and the Chinese Remainder Theorem reassembles the whole private key. The classic victims are key-agreement implementations (ECDH) that use an attacker-supplied public key directly. For Bitcoin's secp256k1 the cofactor is 1, so there are no small subgroups inside the curve; the danger is a point that is on some other curve entirely. Accepting a 65-byte blob and trusting its prefix is exactly the mistake this page avoids: the prefix is parsed, then the equation is verified, then — and only then — the key is hashed.
3. Compressed and uncompressed are two spellings of one point
Compression is not lossy and it is not a hack. Given X, the equation
has exactly two solutions, Y and p − Y. Because p is odd,
p − Y ≡ −Y flips the lowest bit, so those two roots always have opposite parity: one is
even, the other odd. A single bit — "is y even or odd?" — therefore identifies the point completely, and that
bit is exactly what the 02/03 prefix stores. Going the other way, decompression is a
real computation but a cheap one: since p ≡ 3 (mod 4), the square root has a closed form,
Y = (X³ + 7)(p+1)/4 mod p, after which the parity is fixed by negating if necessary.
So both conversions are lossless in both directions. The practical consequence is the part people get wrong: the two serializations are different byte strings, they hash to different values, and they therefore produce different addresses from one and the same private key.
| Uncompressed | Compressed | |
|---|---|---|
| Size | 65 bytes / 130 hex | 33 bytes / 66 hex |
| Prefix | 04 | 02 or 03 by y parity |
| Information carried | X and Y in full | X plus one parity bit |
| hash160 (demo key) | 3f0e966dc089c611a9c1d03bd4f69ea53b0223f9 | 21f57b6debcfc5b67182dfb4af1641f0a8189012 |
| P2PKH address (demo key) | 16kR3eiswUY6tmGnxZhwQmW6LAvTLGWG2G | 146ZNjH7XTXnMd1ofe3z7CL2i8WM7N2UqT |
| Bytes pushed when spending | 139 (one input, 72-byte signature) | 107 (same assumption) |
| Usable in a SegWit v0 spend? | no — BIP143 requires compressed keys | yes |
| Introduced | the original 2009 client | Bitcoin 0.6, 2012 |
4. The hybrid 06/07 prefixes
A "hybrid" key is 65 bytes long — X and Y both present — but its prefix claims to know the parity of Y:
06 for even, 07 for odd. In other words it carries the information twice. The form was
never produced by Bitcoin Core; it survived because some early libraries accepted it, and "accepted by some
implementations" is the worst possible status for a wire format. Two failure modes follow:
- Ambiguity. A producer can write a prefix that contradicts the Y it sends
(
07with an even Y). Strict parsers reject it, lenient ones ignore the prefix, and the two camps disagree about the same bytes — a consensus-style split at the library level. - No benefit. Hybrid form saves nothing: it is 65 bytes, exactly like
04.
Hybrid keys were removed from the suggested standards and no modern wallet generates them. The library
behind this page does recognise 65-byte 04, 06 and 07 inputs and
verifies the curve equation for all of them — but it does not cross-check the hybrid prefix against
the parity of Y, so a 07-prefixed key with an even Y is accepted as a valid point. That leniency
is precisely why the form is dangerous: the same bytes can be judged differently by different libraries. This
page therefore refuses 06/07 outright and tells you to change that one byte to
04 before continuing. Do that, then confirm that the address you get back is the address that
actually holds the coins.
This page requires the canonical 04 form and will tell you so if you paste a compressed or
hybrid key. If you have a 06/07 key from an old tool, convert it to
04 (change one byte) before feeding it to anything, then verify the address it produces
matches the address that holds the coins.
5. Worked example — the real demo key
| Step | Value |
|---|---|
| Input (130 hex) | 04ff812e26116a9aa140abe629e7f8a38401653caf925119def59ed3758c67ee808f49cde13c7ffd64f1d730bf87a743a578eda4971ddac4a08118160732b424ae |
| Prefix | 04 → uncompressed, 65 bytes |
| X | ff812e26116a9aa140abe629e7f8a38401653caf925119def59ed3758c67ee80 |
| Y | 8f49cde13c7ffd64f1d730bf87a743a578eda4971ddac4a08118160732b424ae |
| Y parity | final hex digit e → even → compressed prefix 02, hybrid prefix 06 |
Y² mod p | 174ca53008928cd3c9c380e12c4b1dee0c5a0b6d851b1c472a58d744ca28c6dc |
X³ + 7 mod p | 174ca53008928cd3c9c380e12c4b1dee0c5a0b6d851b1c472a58d744ca28c6dc — identical, so the point is on the curve |
| hash160 of the 65-byte key | 3f0e966dc089c611a9c1d03bd4f69ea53b0223f9 |
| P2PKH address (uncompressed) | 16kR3eiswUY6tmGnxZhwQmW6LAvTLGWG2G |
| Compressed serialization | 02ff812e26116a9aa140abe629e7f8a38401653caf925119def59ed3758c67ee80 |
| hash160 of the 33-byte key | 21f57b6debcfc5b67182dfb4af1641f0a8189012 |
| P2PKH address (compressed) | 146ZNjH7XTXnMd1ofe3z7CL2i8WM7N2UqT |
| P2SH-P2WPKH (compressed only) | 3DZT76KyKyc5zkzvLugP8umgt4RPY4XPQw |
| P2WPKH (compressed only) | bc1qy86hkm0telzmvuvzm76279jp7z5p3yqjnaerk6 |
| x-only 32-byte form, hashed for reference | 4d75c804c152bcc1e66a56cd6899f442b63dbf6c → 184a8MvQDPfePQPiVw3DUnAusPPvJmLGj7 (not a spendable address form) |
One point, one private key, and six different destination strings. Note the last row: hashing the x-only form is a common accident in code that juggles Taproot keys, and it produces an address that no wallet will ever look at.
6. Watch-only wallets: what a public key can do without you
Everything on this page except the signature is computable from the public key alone. That is the basis of a watch-only wallet: give a server or a phone the public key (or, more commonly, an extended public key from BIP32), and it can derive every address you will ever use, track every payment, and compute your balance — without ever holding a secret that can spend.
Useful, and worth being clear-eyed about:
- It sees everything. A leaked public key means the complete history and balance of that key is readable by whoever holds it. The money cannot move, but "cannot move" is not privacy.
- It is the normal design. Hardware wallets, Lightning nodes, merchant accounting and block explorers all rely on exactly this asymmetry. The public key is not junk you can leave lying around; it is an identifier that links all your payments together.
- It is not a spending capability. To sign you need
k. When you check that a received public key is on the curve, you are checking that it is a real point — not that you can use it.
7. Where this fits in the chain
- Upstream: private key → uncompressed public key produces exactly this 130-digit string.
- Sibling: compressed public key → hash160 → addresses does the same job for the 33-byte form.
- Downstream: hash160, then the uncompressed P2PKH address, or P2WPKH if you switch to the compressed serialization first.
8. Security notes
- Always verify the curve equation before using a public key sent to you by someone else. Rejecting invalid points is a security control, not a formality.
- Also check that
X < pandY < p; a coordinate outside the field is not a point at all, and some libraries only discover this when the arithmetic silently wraps. - Prefer the compressed form for anything new. It is smaller, cheaper to spend, and mandatory for SegWit; the uncompressed form exists to recover coins that were paid to it before 2012.
- Never derive a SegWit program from the uncompressed key. A
bc1q…address computed from hash160(65-byte key) looks perfectly valid and cannot be spent under BIP143's compressed-key rule.
9. Common mistakes
- Assuming both serializations give one address. They give two, and coins live at exactly one of them.
- Hashing the wrong bytes. hash160 is applied to the serialized key, prefix included. Hashing just X, or the x-only form, produces a third and useless address.
- Trimming leading zeros. Coordinates are fixed-width, big-endian. Shortening the string changes the point.
- Trusting the length alone. 130 hex digits prove nothing about whether the point exists; the curve check is what proves it.
- Reusing one public key for many payments. It works, and it permanently links those payments on-chain.
10. Quick reference
| Item | Value |
|---|---|
| Layout | 04 ‖ X ‖ Y, 65 bytes, 130 hex digits |
| Curve test | Y² ≡ X³ + 7 (mod p) |
| Field prime | 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F |
| Compression | drop Y, keep its parity in the prefix: 02 even, 03 odd |
| Decompression | Y = (X³+7)(p+1)/4 mod p, then fix parity |
| Address from it | Base58Check(0x00 ‖ hash160(65-byte key)) |
| Hybrid prefixes | 06/07 — deprecated, avoid |
| SegWit compatible? | No; witness v0 requires the compressed form |