ECDSA (Elliptic Curve Digital Signature Algorithm)
1. Background: What is ECDSA?
ECDSA is a digital signature algorithm based on Elliptic Curve Cryptography (ECC).
- It’s used to sign messages (prove authenticity) and verify signatures (prove origin & integrity).
- Widely used in Bitcoin, Ethereum, TLS certificates, SSH, JWTs, etc.
- Its security is based on the hardness of the Elliptic Curve Discrete Logarithm Problem (ECDLP).
2. Key Concepts You Need First
(a) Finite Fields
Cryptography works over finite fields (like modular arithmetic). For example:
In mod 7:
3 + 5 ≡ 1 (mod 7)
3 × 5 ≡ 1 (mod 7)
(b) Elliptic Curves
An elliptic curve is defined by an equation like:
Demo: Elliptic Curves
y² = x³ + ax + b (mod p)
where p
is a prime (so we’re in a finite field).
These curves aren’t circles/ellipses — instead, they form a special set of points with useful math properties.
(c) Group Law (Point Addition)
On elliptic curves, we define:
- Point addition: adding two points gives another point on the curve.
- Scalar multiplication: repeating addition many times (like multiplication in normal math).
This operation is easy one way, but hard to reverse — the basis of ECC security.
3. ECDSA Key Generation
- Choose a standard elliptic curve (like secp256k1 in Bitcoin).
- Pick a random private key
d
(a number in[1, n-1]
, wheren
is the order of the curve). - Compute public key
Q = d × G
, whereG
is the generator point on the curve.
So:
- Private key = number
d
- Public key = point
Q
4. Signing a Message
To sign a message m
with private key d
:
-
Compute hash:
z = HASH(m)
(SHA-256, for example). -
Pick a random number
k
(nonce, must be secret & unique). -
Compute point:
R = k × G
, letr = R.x mod n
.- If
r = 0
, restart.
- If
-
Compute:
s = k⁻¹ (z + r·d) mod n
.- If
s = 0
, restart.
- If
-
Signature = pair
(r, s)
.
5. Verifying a Signature
To verify (r, s)
against message m
and public key Q
:
-
Check
r, s
are in range[1, n-1]
. -
Compute hash:
z = HASH(m)
. -
Compute inverse:
w = s⁻¹ mod n
. -
Compute:
- .
Let
x = X.x mod n
. -
Signature valid if
x = r
.
🔑 Key weakness: If is ever reused or leaked → private key can be recovered (this happened in Bitcoin/PS3 hacks).
6. Why ECDSA Works
- Signing equation:
s = k⁻¹(z + r·d)
- Verification recombines
G
andQ
so that the only wayr
matches is if the signer knewd
. - Security: Breaking ECDSA means solving ECDLP, which is computationally infeasible.
7. Implement in java
Step 1: Define a Small Finite Field and Curve
For simplicity:
- (prime modulus)
- Curve:
- Generator point
- Order (n) = 19 (we’ll just pick a small prime for the cycle length)
# Finite field modulo
p = 17
# Curve parameters: y^2 = x^3 + ax + b (mod p)
a, b = 2, 2
# Generator point
G = (5, 1)
n = 19 # order of the generator (for toy curve)
Step 2. Modular Inverse (needed for division)
We’ll use the extended Euclidean algorithm to compute inverses mod p.
def modinv(k, p):
"""Modular inverse using Extended Euclidean Algorithm"""
if k == 0:
raise ZeroDivisionError("division by zero")
return pow(k, -1, p) # Python 3.8+ supports this
Step 3. Point Addition on the Curve
We need point addition and doubling.
def point_add(P, Q):
if P is None: return Q
if Q is None: return P
(x1, y1) = P
(x2, y2) = Q
if x1 == x2 and (y1 != y2 or y1 == 0):
return None # point at infinity
if P == Q:
# slope = (3*x1^2 + a) / (2*y1)
m = (3 * x1 * x1 + a) * modinv(2 * y1, p) % p
else:
# slope = (y2 - y1) / (x2 - x1)
m = (y2 - y1) * modinv(x2 - x1, p) % p
x3 = (m * m - x1 - x2) % p
y3 = (m * (x1 - x3) - y1) % p
return (x3, y3)
Step 4. Scalar Multiplication
Multiply a point by an integer (repeated addition).
def scalar_mult(k, P):
R = None
while k > 0:
if k & 1:
R = point_add(R, P)
P = point_add(P, P)
k >>= 1
return R
Step 5. Key Generation
Pick random private key , compute public key .
import random
def generate_keypair():
d = random.randrange(1, n) # private key
Q = scalar_mult(d, G) # public key
return d, Q
Step 6. ECDSA Signing
Follow the ECDSA signing steps.
def sign(m, d):
z = m % n # pretend "hash" is just m mod n
while True:
k = random.randrange(1, n)
R = scalar_mult(k, G)
r = R[0] % n
if r == 0:
continue
s = (modinv(k, n) * (z + r * d)) % n
if s == 0:
continue
return (r, s)
Step 7. ECDSA Verification
Verify a signature.
def verify(m, sig, Q):
r, s = sig
if not (1 <= r < n and 1 <= s < n):
return False
z = m % n
w = modinv(s, n)
u1 = (z * w) % n
u2 = (r * w) % n
X = point_add(scalar_mult(u1, G), scalar_mult(u2, Q))
if X is None:
return False
return (X[0] % n) == r
Step 8. Test It Out
# Key generation
d, Q = generate_keypair()
print("Private key:", d)
print("Public key:", Q)
# Sign a message
m = 13 # pretend message = 13
sig = sign(m, d)
print("Signature:", sig)
# Verify
print("Valid?", verify(m, sig, Q))
✅ This should output something like:
Private key: 7
Public key: (0,6)
Signature: (10, 4)
Valid? True
2. ECDSA (Elliptic Curve Digital Signature Algorithm)
Signing a message
-
Hash the message: .
-
Choose a random integer (ephemeral secret, must be unique and hidden).
-
Compute the point .
- Let (use the x-coordinate).
- If , restart.
-
Compute .
- If , restart.
-
Signature is the pair .
Verifying a signature
3. Schnorr Signatures (cleaner alternative)
Schnorr is mathematically simpler and has nice properties (linear, provably secure under discrete log).
Signing
- Hash the message: .
- Choose random nonce .
- Compute .
- Compute challenge .
- Compute response .
- Signature is .
Verifying
Given signature :
-
Compute .
-
Check if .
- If true, signature is valid.
🔑 Advantages over ECDSA:
- Simpler math.
- No fragile dependency on .
- Supports batch verification (verify many sigs at once).
- Enables signature aggregation (combine many sigs into one). → This is why Bitcoin Taproot adopted Schnorr.
4. Side-by-Side Comparison
Feature | ECDSA | Schnorr |
---|---|---|
Complexity | More steps, fragile with | Very clean & simple |
Security proof | Heuristic | Provable under ECDLP |
Multi-signatures | Awkward | Natural & efficient |
Adoption | Widely used (Ethereum, TLS) | Growing (Bitcoin Taproot, research) |
5. Next Step for You
Since you’re a blockchain engineer, the most useful practice is:
- Implement ECDSA (sign + verify) on
secp256k1
(Bitcoin curve). - Implement Schnorr on the same curve.
- Compare how they behave with real messages.
Would you like me to show you code examples (Python or Rust) for:
- ECDSA sign/verify, and
- Schnorr sign/verify so you can see the math in action?