Private Key Tools

secp256k1 point arithmetic

Add two curve points, double a point, or multiply the generator by a scalar — the raw group law that every Bitcoin public key is built from. Feed it k·G and watch the private key become a point; add a point to its own negation and watch it collapse into the point at infinity.

mul multiplies the fixed generator G by a scalar, add uses both operands, double ignores operand B and computes 2·A.
In mul mode A is a scalar — a hex private key in [1, n−1] (the placeholder is one). In add and double mode A is a point: the letter G for the generator, or a compressed (66 hex), uncompressed (130 hex) or x-only (64 hex) public key. Shorter scalars are left-padded with zeros.
The second point, used only in add mode; ignored in mul (which always multiplies G) and in double. Empty means the generator G. To see the point at infinity, add a public key to the same key with its 02/03 prefix flipped.
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

This is a bare-metal playground for the group law of secp256k1, the elliptic curve Bitcoin uses. It offers three operations and nothing else:

mul:  R = k · G    add:  R = P + Q    double:  R = P + P
operands (scalar / points)→ group law on y² = x³ + 7 (mod p)→ result point (x₃, y₃)→ 02/03 ‖ x or 04 ‖ x ‖ y

Everything is computed live on this server in pure PHP with GMP-backed big integers. The output shows the operands as they were parsed, the curve constants actually used, the resulting point, its parity, both standard serializations, whether the result is the point at infinity, and an independent on-curve check of the answer.

1. The curve and why its points form a group

secp256k1 is the set of pairs (x, y) with coordinates taken modulo the prime p that satisfy

y² ≡ x³ + 7  (mod p)

plus one extra element, the point at infinity ∞. Because the equation is modular, this is not a smooth arch drawn on paper but a scattered set of roughly n points in a 256-bit-wide finite grid. The useful miracle is that you can define an addition on those points which is associative, commutative, has an identity (∞) and gives every point an inverse (−P). Any set with those four properties is an abelian group, and a group is exactly the structure you need in order to iterate an operation — which is what "multiply by an integer" means.

The inverse of a point is free: if (x, y) is on the curve then so is (x, −y), because the curve equation only contains y². So −P = (x, p − y). Note that p − y has the opposite parity from y, a fact the compressed encoding uses.

ConstantValueMeaning
Field prime p0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2FCoordinates live in [0, p−1]. Equal to 2²⁵⁶ − 2³² − 977, decimal 115792089237316195423570985008687907853269984665640564039457584007908834671663.
Group order n0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141The number of points (including ∞). Private keys live in [1, n−1]. Decimal 115792089237316195423570985008687907852837564279074904382605163141518161494337.
Generator Gx0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798The conventional base point. Every Bitcoin public key is a multiple of it.
Generator Gy0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8Even, which is why the compressed form of G starts with 02.
Cofactor h1The curve group has exactly n points, and n is prime. See §4.
p mod 43This is what makes modular square roots cheap: √a = a^((p+1)/4).
p and n are different numbers

Nearly every beginner bug on this curve comes from mixing them up. p bounds the coordinates and all field arithmetic is done mod p. n bounds the scalars and all scalar arithmetic is done mod n. They are numerically close to 2²⁵⁶ and therefore easy to confuse, but using the wrong one produces garbage that still looks like a valid 32-byte number.

2. The group law, geometrically: chords and tangents

The classical construction works over the real numbers, where you can draw it. Take two points P and Q on the curve and draw the straight line through them. A cubic curve meets a line in exactly three points (counted with multiplicity), so there is a third intersection point R. Define the sum as R reflected across the x-axis:

P ⊕ Q := −R, where line(P, Q) ∩ curve = { P, Q, R }     2P := −T, where tangent(P) ∩ curve = { P, T }

Why the reflection? Because the reflection of a curve point is still on the curve, and without it the construction fails to be associative — the reflected version is the one that makes (P+Q)+R = P+(Q+R) hold. Three special cases are worth naming, because they are exactly where the implementation has to branch:

  1. P = Q. There is no unique line through one point; the limiting case is the tangent line at P. That is the "tangent" in "chord and tangent" and it is what doubling computes.
  2. Q = −P (same x, opposite y). The line through them is vertical, it meets the curve only at those two points, and the third intersection is the point at infinity. So P + (−P) = ∞, exactly as an additive inverse should.
  3. P = ∞ or Q = ∞. Since ∞ is the identity, the sum is simply the other operand.

Over a finite field "the line through P and Q" is still meaningful — it is the set of points satisfying a linear equation mod p — and the same three-intersections argument holds. The drawing stops being useful, but the algebra does not.

3. The group law, algebraically

Division by a non-zero element mod p is multiplication by its modular inverse, so every "slope" below is a real, computable field element. With λ the slope of the chord (or tangent) through the points being added, and (x₃, y₃) the result:

add (P ≠ ±Q):  λ = (y₂ − y₁) / (x₂ − x₁)     double (P = Q):  λ = (3x₁²) / (2y₁)
x₃ = λ² − x₁ − x₂     y₃ = λ(x₁ − x₃) − y₁    (all mod p)

That is the entire group law. Notice that x₃ depends only on λ and the two x coordinates, and that y₃ is then fixed by reflecting through the line. Notice also that the formula is symmetric in x₁ ↔ x₂ but the y terms are not, which is why P + Q = Q + P holds while P + (−P) needs its own case.

A single addition costs one modular inversion (the expensive part: here it is done by Fermat exponentiation, a^(p−2)) plus two or three modular multiplications/squarings. Real libraries use projective or Jacobian coordinates to defer the inversion, trading it for extra multiplications, because inversions are roughly a hundred times more expensive than multiplications.

CaseConditionFormula usedResult
Generic additionx₁ ≠ x₂chord slope (y₂−y₁)/(x₂−x₁)a normal curve point
DoublingP = Q (so x₁ = x₂, y₁ = y₂)tangent slope 3x₁²/(2y₁)a normal curve point
Inverse pairx₁ = x₂ and y₁ + y₂ ≡ 0division by zero is avoided∞, the identity
IdentityP = ∞ or Q = ∞short-circuitthe other operand
Zero yy₁ = 0 (doubling)2y₁ ≡ 0∞; no such point exists on secp256k1

4. Why ∞ is the identity, and when it appears

The point at infinity is not a coordinate pair and cannot be serialized as a public key — the standard encodings simply have no room for it. It exists as the answer to "what is the third intersection when the line is vertical", and it behaves exactly like zero in ordinary arithmetic:

P + ∞ = ∞ + P = P    ∞ + ∞ = ∞    n · G = ∞

Three situations produce it, and this page shows whether the result is ∞ explicitly:

5. Cofactor 1, cyclicity, and why every public key is a multiple of G

The number of points on the curve is h · n with h the cofactor. For secp256k1, h = 1, so the group order is n, and n is prime. This has several very convenient consequences:

6. Double-and-add: how k · G is actually computed

There is no closed-form shortcut for scalar multiplication, so implementations iterate the bits of the scalar. The version in this codebase walks the 256 bits from most significant to least:

R = ∞                          # the identity
for bit in bits_of(k):         # 256 iterations for a 256-bit scalar
    R = double(R)              # R = R + R
    if bit == 1:
        R = add(R, G)          # R = R + G
return R                       # R = k · G

The cost is one doubling per bit plus one addition per set bit. For the demo private key 0824c314…171ca the bit census is 256 bits with 116 of them set, so the loop performs 256 doublings and 116 additions — 372 point operations, each of which internally is one inversion plus a few multiplications. Production code uses windowed or fixed-window methods (precomputing G, 2G, 3G, …, 15G and processing four bits at a time) to cut that count by roughly a third, and a Montgomery ladder when the scalar must stay secret.

OperationPoint ops (256-bit scalar / one call)Dominant cost
double — 2 · P1 doubling1 inversion + ~2 squarings + ~2 multiplications
add — P + Q (P ≠ ±Q)1 addition1 inversion + ~3 multiplications/squarings
add — P + (−P)0 (case detected)one comparison of coordinates; returns ∞
mul — k · G256 doublings + (popcount of k) additionsthe inversion in each step, so ~hundreds of inversions
mul — k · G, windowed (real libraries)~64 doublings + ~64 additions + precomputationsame, but 2–3× fewer of them
Why the reverse direction is impossible

Going from k to k·G takes 256 iterations. Going from the point back to the scalar is the elliptic curve discrete logarithm problem; the best known general algorithm (Pollard's rho) needs on the order of √n ≈ 2¹²⁸ steps. That asymmetry — cheap forwards, astronomically expensive backwards — is the entire reason public keys can be published.

7. Timing, side channels and what "constant time" means here

The pseudocode above is a security hazard if the scalar is a real private key, because its control flow depends on the secret: a scalar bit of 0 skips the addition, a bit of 1 performs it. Any observer who can measure how long a signature or a derivation takes, or watch the power drawn by the chip, can recover the scalar bit by bit. This is not theoretical: timing attacks on naive ECDSA implementations have recovered keys across a network.

Constant time means the sequence of executed operations and memory accesses does not depend on secret values — only the data does. Concretely, implementations achieve it by always doing both the doubling and the addition and then selecting the right result arithmetically; by using unified addition formulas with no special cases; by scalar blinding (computing (k + r·n)·G for a random r, which gives the same point but a different bit pattern); and by point blinding. libsecp256k1 combines several of these and is written specifically to avoid secret-dependent branches.

This page is a teaching tool, not a wallet

The PHP + GMP implementation behind this page is not constant time: GMP bignums have data-dependent timings, the double-and-add loop branches on scalar bits, and there is no blinding. It is perfectly safe for experimenting with public inputs like the ones on this page, and it must never be used to process a private key that protects money. Use a hardware wallet or a well-tested constant-time library for that.

8. Worked example: doubling G

The most-cited sanity check on any secp256k1 implementation is 2G. Using the tangent formula with the real constants above, this page computes:

StepValue
StartG = (79be667e…f81798, 483ada77…10d4b8)
Slope λ = 3Gx² / (2Gy) mod preduced to a 256-bit field element
x₃ = λ² − 2Gxc6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5
y₃ = λ(Gx − x₃) − Gy1ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a
Parity of y₃even → compressed prefix 02
2G compressed02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5
2G uncompressed04c6047f…b95c709ee51ae168…50cfe52a (65 bytes)
Independent checkSet the operation to double with A = G: the page doubles the generator and then computes pointMul(2, G) as a cross-check, reporting that the two match — they are the public key of private key 2
hash160(2G) / P2PKH06afd46bcdfd22ef94ac122aa11f241244a37ecc → 1cMh228HTCiwS8ZsaakH8A8wze1JR5ZsP
WIF of private key 2KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU74NMTptX4 (compressed)

Two more checks you can reproduce with the form above, both of which exercise the identities from §5:

9. Common mistakes

10. Quick reference

ItemValue
Curvey² = x³ + 7 over GF(p), p = 2²⁵⁶ − 2³² − 977
Group ordern (prime, 256 bits), cofactor h = 1
Identity∞ — no coordinates, cannot be serialized
Inverse−P = (Px, p − Py); flips the 02/03 prefix
Add slopeλ = (y₂ − y₁)(x₂ − x₁)⁻¹ mod p
Double slopeλ = 3x₁²(2y₁)⁻¹ mod p
Resultx₃ = λ² − x₁ − x₂, y₃ = λ(x₁ − x₃) − y₁ (all mod p)
Scalar cost256 doublings + one addition per set bit of k
Public keyk · G, serialized as 02/03 ‖ x (33 B) or 04 ‖ x ‖ y (65 B)
Valid scalars1 ≤ k ≤ n−1; validated with Btc::normalizePrivateKey