Building Bitcoin’s secp256k1 Curve and ECDSA from Scratch in Python



This content originally appeared on DEV Community and was authored by 0xMouiz

Bitcoin’s secp256k1 Curve and ECDSA from Scratch in Python<br>

Intro

Elliptic curve cryptography (ECC) powers the security of Bitcoin, Ethereum, and countless secure systems.
One of the most famous curves, secp256k1, is the backbone of Bitcoin addresses and Ethereum keys.

While libraries like secp256k1 and ecdsa abstract away the math, building it yourself is a great way to understand how elliptic curves and ECDSA signatures work.

In this post, we’ll walk through my minimal Python implementation of secp256k1 — covering:

  • The math behind the curve
  • Point addition, doubling, and scalar multiplication
  • Private/public key generation
  • ECDSA signing and verification with Keccak-256

1. What is secp256k1?

secp256k1 is a Koblitz curve defined over a finite field. Its equation is:

y² ≡ x³ + 7 (mod p)

Where:

  • p is a large prime
  • a=0, b=7
  • G is the generator point
  • n is the order of the curve
  • It’s used in Bitcoin, Ethereum, and other blockchain systems because it offers strong security and fast computation.

2. Implementing the Curve

We start with a Point class for elliptic curve points, supporting:

  • Addition (P+Q)
  • Doubling (2P)
  • Scalar multiplication (kP)
class Point:
    def __add__(self, other):
        if self.is_at_infinity():
            return other
        if other.is_at_infinity():
            return self
        if self == other:
            return self.double()
        if self.x == other.x and (self.y + other.y) % self.curve.p == 0:
            return Point(None, None, self.curve)  # point at infinity
        s = ((other.y - self.y) * pow(other.x - self.x, -1, self.curve.p)) % self.curve.p
        x_r = (s**2 - self.x - other.x) % self.curve.p
        y_r = (s * (self.x - x_r) - self.y) % self.curve.p
        return Point(x_r, y_r, self.curve)

The Curve class enforces the curve equation and provides helper methods like _tangent_slope _for doubling.

3. secp256k1 Parameters

We define the constants exactly as per the official specification:

p  = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F
a  = 0
b  = 7
Gx = 0x79BE66...
Gy = 0x483ADA...
n  = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
h  = 1

curve = Curve(a, b, p, n, h, Gx, Gy, "secp256k1")

4. Key Generation

Private key: random integer in [1,n−1]
Public key: priv × G

5. ECDSA Signing

We use Keccak-256 for hashing (Ethereum’s choice) and the standard ECDSA formula:

def sign(msg, private_key):
    z = int.from_bytes(keccak256(msg), "big")
    while True:
        k = secrets.randbelow(curve.n)
        R = k * curve.G
        r = R.x % curve.n
        s = (modinv(k, curve.n) * (z + r * private_key)) % curve.n
        if r != 0 and s != 0:
            return (r, s)

6. ECDSA Verification

The verifier computes:
u1 = z × w
u2 = r × w
P = u1 × G + u2 × Q
Valid if Px mod n = r

7. Demo Run

python3 main.py

Example output:

[+] Private key: 0x1393b6573adf24c61b73561768d9ea4ba1670dcc77554f25938cbca621ed7645
[+] Public key: 0475ca8eaf8393...
[+] Signature: (2313066..., 8090080...)
[+] Signature valid? True

8. Why This Matters

This code is not for production — it’s educational.
It shows exactly how:

  • Bitcoin addresses are derived
  • Ethereum signs transactions
  • ECDSA math works without relying on “magic” library calls

9. Full Source Code

https://github.com/0xMouiz/python-secp256k1


This content originally appeared on DEV Community and was authored by 0xMouiz