Private key → compressed public key
Multiply the generator point G by your private key scalar k on the secp256k1 curve, then serialize the resulting point into the 33-byte form that starts with 02 or 03. This single step is where a secret number becomes something shareable, and it is the step every other address type in Bitcoin is built on.
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 one 256-bit number — the private key k — and it computes the
compressed public key. Inside the server this is one operation:
1. What a private key really is
A Bitcoin private key is not a file, a password or a random blob of bytes. It is a single integer — a scalar in the language of elliptic-curve cryptography — that satisfies:
Two boundary values are excluded, and this matters in practice:
k = 0would give0 · G, the so-called point at infinity, which has no coordinates and cannot be serialized into a public key.k ≥ nwraps around, because the curve's point group is cyclic of ordern:n · G = ∞, so(n+1) · G = G. A key ofn+1would be a legal-looking 32-byte number that silently behaves like1.
The practical upper bound is therefore about 2256, but not exactly: the search space holds
n − 1 ≈ 1.158 × 1077 usable keys, which is roughly the number of atoms in the
observable universe divided by a billion. Guessing one by brute force at a trillion keys per second would
still take around 1058 years.
| Property | Value |
|---|---|
| Size | 256 bits / 32 bytes / 64 hex digits |
| Valid range | 1 … n−1 |
| Success probability of a blind guess | 1 in 2256 (about 1.16 × 1077 keys) |
| What it must be | Uniformly random, or derived from uniformly random entropy |
| What it must never be | A hash of a human-chosen phrase, a counter, a timestamp, a book quote |
Every large Bitcoin theft that did not involve a compromised machine came down to a key that was
predictable: a weak RNG seeded from the clock, a brainwallet phrase, a key made from a phone's
serial number. The maths here is unbreakable; the entropy source around it is where people lose money.
Use random_bytes(32) (which this server does) or a hardware wallet's secure element.
2. The curve: why a public key is a point
Bitcoin uses the curve secp256k1, defined over the prime field of integers modulo
p:
Any pair (x, y) satisfying that equation is a point on the curve. Because the equation is taken
modulo p, the "curve" is not a smooth arc but a scattered set of points in a 256-bit wide finite
grid — yet it still forms a mathematical group, which is what makes cryptography possible on it.
Points can be added (geometrically: draw a line through two points, find the third intersection, reflect it across the x-axis) and therefore also multiplied by an integer by repeated addition. That group law is the entire engine of Bitcoin key derivation.
| Constant | Value |
|---|---|
| Field prime p | 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F |
| Curve order n | 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 |
| Generator Gx | 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798 |
| Generator Gy | 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8 |
| Cofactor h | 1 (the groups are the same size — no small-subgroup tricks needed) |
Note that p and n are different numbers and it is a common beginner bug to
confuse them. p bounds the coordinates; n bounds the private key.
3. How P = k·G is actually computed
There is no closed-form shortcut. The standard method is double-and-add, which walks the
256 bits of k from most significant to least:
R = point at infinity
for bit in bits_of(k): # 256 iterations
R = double(R) # R = R + R
if bit == 1:
R = add(R, G) # R = R + G
return R
That is about 256 doublings and ~128 additions — a few hundred field operations, which is why a modern laptop can do tens of thousands of these per second and this PHP implementation with GMP does roughly 80 per second.
Going from k to P takes 256 steps. Going from P back to
k — the elliptic curve discrete logarithm problem — has no known efficient
algorithm: the best general method (Pollard's rho) needs on the order of √n ≈ 2128 operations.
This asymmetry is the whole reason a public key can be published safely.
The naive loop above branches on the secret bits, so its running time and power draw leak information. Production implementations use constant-time scalar multiplication and random blinding. This page is a teaching tool; use libsecp256k1 or a hardware wallet for real money.
4. Serializing a point: 33 bytes or 65 bytes
A point is two 256-bit coordinates, so the obvious encoding is 64 bytes plus a tag. SEC1 defines two standard ways:
| Form | Encoding | Length | Leading byte |
|---|---|---|---|
| Uncompressed | 04 ‖ X ‖ Y | 65 bytes (130 hex) | 04 |
| Compressed (even Y) | 02 ‖ X | 33 bytes (66 hex) | 02 |
| Compressed (odd Y) | 03 ‖ X | 33 bytes (66 hex) | 03 |
| Hybrid (legacy) | 06/07 ‖ X ‖ Y | 65 bytes | 06/07 |
| x-only (BIP340, Taproot) | X | 32 bytes (64 hex) | none |
5. The parity trick: why 32 bytes are enough
Compression is not a lossy hack — it is exact, because Y is fully recoverable from
X. For a given X, the curve equation gives
which has exactly two solutions, Y and p − Y. Those two roots always have
opposite parity: one is even, the other is odd (this holds because p is odd, so
p − Y ≡ −Y flips the lowest bit). So a single bit — "is Y even or odd?" — is enough to pick
between them. That bit is exactly what the 02/03 prefix stores.
Decompression is therefore a real computation: add the constant 7 to the cube of X, take the modular
square root (feasible in closed form because p ≡ 3 (mod 4), giving
Y = (X³+7)(p+1)/4 mod p), then negate if the requested parity does not match.
6. Worked example
These are the real values this page produces for the sample key
0824c314…171ca:
| Step | Value |
|---|---|
| k | 0824c314772b2c2859c889471390a36bf66e53a1ca1642f96f0f2c9307a171ca |
| X of P = k·G | ff812e26116a9aa140abe629e7f8a38401653caf925119def59ed3758c67ee80 |
| Y of P | 8f49cde13c7ffd64f1d730bf87a743a578eda4971ddac4a08118160732b424ae |
| Y parity | last hex digit is e → even, so the prefix is 02 (an odd Y would give 03) |
| Compressed | 02ff812e26116a9aa140abe629e7f8a38401653caf925119def59ed3758c67ee80 |
| Uncompressed | 04ff812e…8f49cd…b424ae (65 bytes) |
| hash160 (from compressed) | 21f57b6debcfc5b67182dfb4af1641f0a8189012 |
| hash160 (from uncompressed) | 3f0e966dc089c611a9c1d03bd4f69ea53b0223f9 |
| P2PKH address (C) | 146ZNjH7XTXnMd1ofe3z7CL2i8WM7N2UqT |
| P2PKH address (U) | 16kR3eiswUY6tmGnxZhwQmW6LAvTLGWG2G |
Notice the last two rows: one private key, two completely different addresses. The page's own result panel recomputes all of these live, so you can verify the claim yourself.
7. Compressed vs uncompressed — why anyone cares
Both encodings describe the same point and both are valid signatures-wise, but they lead to different addresses, and that has real consequences.
| Compressed (C) | Uncompressed (U) | |
|---|---|---|
| Public key size | 33 bytes | 65 bytes |
| hash160 input | 02/03‖X | 04‖X‖Y |
| Resulting P2PKH address | 146ZNjH7…2UqT | 16kR3eis…WG2G |
| WIF prefix | K…/L… (33-byte payload + 01 flag) | 5… |
| scriptSig size when spending | ~107 bytes | ~139 bytes |
| Introduced | Bitcoin 0.6 (2012), BIP-suggested | Satoshi's original client |
| Current status | The default everywhere | Legacy; kept for old funds |
A private key does not know whether it is "compressed" or not. That flag lives in the WIF string, not in the key. If you import a compressed WIF into a wallet but the coins sit at the uncompressed address (or vice versa), the wallet will look at the wrong address, show a zero balance, and you will conclude that your money is gone. It usually is not — but you need a wallet that derives both forms, or a tool like this one, to find out which address holds the coins.
8. Where the compressed public key goes next
- P2PKH (
1…):Base58Check(0x00 ‖ hash160)— see private key → P2PKH address. - P2WPKH (
bc1q…):bech32("bc", 0, hash160)— the compressed key is mandatory here; witness programs are always 20 bytes. - P2SH-P2WPKH (
3…):Base58Check(0x05 ‖ hash160(0x0014 ‖ hash160)). - P2TR (
bc1p…): a different path entirely — the internal key is tweaked withTapTweakand only the x coordinate of the output key is used.
9. Security notes
- A public key is safe to publish. It reveals nothing usable about
k, assuming the discrete log problem stays hard. - A public key does leak some information: once a key has signed a transaction, the address is publicly tied to that public key, which slightly reduces the attacker's search space if ECDSA nonce reuse ever occurs. Taproot was partly motivated by hiding keys behind a single point.
- Always validate a received public key with the on-curve check (
Y² ≡ X³ + 7). Accepting an off-curve point enables invalid curve attacks that can recover the private key. This page performs that check and refuses off-curve input. - Quantum computers running Shor's algorithm could solve the discrete log directly. That affects public keys that are already exposed on-chain, not the hash-based addresses that have never spent.
10. Common mistakes
- Confusing the private key with the WIF. The WIF is a Base58Check encoding of the key plus a network byte and a compression flag. They are different strings for the same secret.
- Assuming one private key = one address. One key yields at least five distinct address types, plus testnet variants.
- Treating the public key as the address. The public key is not hashed into a Base58 form by itself; the address is the 20-byte hash of the (encoded) public key.
- Padding errors. A private key of
0x1fis 31 bytes of leading zeros followed by1f— losing those zeros produces a completely different key. - Mixing up p and n.
XandYare reduced modulop;kis reduced modulon.
11. Quick reference
| Item | Value |
|---|---|
| Formula | P = k · G on secp256k1 |
| Input length | 32 bytes (any length accepted, left-padded) |
| Output length | 33 bytes compressed / 65 bytes uncompressed |
| Compressed prefix | 02 = even Y, 03 = odd Y |
| Decompression | Y = (X³+7)^((p+1)/4) mod p, then fix parity |
| Reversible? | No — this is a one-way function (ECDLP) |
| Safe to share? | Yes, the public key can be published |