SECP256k1
Overview
secp256k1 is a Koblitz curve defined over a 256-bit prime field, widely used in Bitcoin, Ethereum, and other cryptocurrencies for digital signatures.
- Type: Koblitz elliptic curve
- Field: 256-bit prime field
- Primary Use: ECDSA digital signatures in blockchain
- Security: Based on the Elliptic Curve Discrete Logarithm Problem (ECDLP)
1. The Curve Equation
The secp256k1 curve follows this simple equation:
Key Parameters
Prime Modulus (p) - Click to expand
p = FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F
In decimal form:
This special form allows for efficient modular arithmetic operations.
Curve Parameters
The simplicity of these parameters (especially ) makes point addition calculations more efficient.
Generator Point (G)
The base point used for all key generation:
Gx = 55066263022277343669578718895168534326250603453777594175500187360389116729240
Gy = 32670510020758816978083085130507043184471273380659243275938904335757337482424
Order of G (n)
The number of points generated by repeated addition of G:
n = FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141
= 115792089237316195423570985008687907852837564279074904382605163141518161494337
All operations (addition, scalar multiplication) are performed modulo p on the curve.
2. Cryptographic Keys
Private Key (d)
A randomly generated integer in the range [1, n-1].
d ∈ [1, n-1]
- Never reuse or share your private key
- Generate it using a cryptographically secure random number generator
- Store it securely (hardware wallets, encrypted storage)
Public Key (Q)
Derived from the private key through scalar multiplication:
Where is the generator point and represents elliptic curve point multiplication.
The Elliptic Curve Discrete Logarithm Problem (ECDLP) makes it computationally infeasible to derive the private key from the public key , even though the reverse operation is trivial.
3. Digital Signature Algorithm (ECDSA)
Signing Process
To create a signature for message m:
-
Hash the message:
z = SHA256(m) -
Generate a random nonce
k:k ∈ [1, n-1]CriticalThe nonce
kmust be:- Truly random
- Never reused across signatures
- Kept secret (nonce reuse or leakage reveals the private key!)
-
Compute point
R:R = k · G
r = R.x mod nIf
r = 0, choose a newkand retry. -
Calculate signature component
s:If
s = 0, choose a newkand retry. -
Output signature:
signature = (r, s)
4. Signature Verification
Given signature (r, s), public key Q, and message m:
-
Verify bounds:
r, s ∈ [1, n-1] -
Hash the message:
z = SHA256(m) -
Compute modular inverse:
w = s^{-1} mod n -
Calculate verification parameters:
u1 = z · w mod n
u2 = r · w mod n -
Compute verification point:
X = u1·G + u2·Q -
Verify:
- If
X = ∞(point at infinity), reject - If
X.x mod n == r, signature is valid ✓ - Otherwise, signature is invalid ✗
- If
The verification process essentially reconstructs the point R used during signing, without knowing the private key or nonce.
5. Python Implementation
You don't need to implement elliptic curve math from scratch. The ecdsa library provides a complete implementation.
Installation
pip install ecdsa
Complete Example
from ecdsa import SigningKey, SECP256k1
import hashlib
# Generate a new key pair
sk = SigningKey.generate(curve=SECP256k1) # private key
vk = sk.verifying_key # public key
print(f"Private key: {sk.to_string().hex()}")
print(f"Public key (compressed): {vk.to_string('compressed').hex()}")
print()
# Message to sign
message = b"Hello, secp256k1!"
print("SIGNING")
print(f"Message: {message.decode()}")
# Hash and sign
z = hashlib.sha256(message).digest()
signature = sk.sign(z)
print(f"Message hash: {z.hex()}")
print(f"Signature: {signature.hex()}")
print()
# Verify signature
print("VERIFICATION")
try:
is_valid = vk.verify(signature, z)
print(f"Signature valid: {is_valid}")
except:
print("Signature valid: False")
Example Output
KEY GENERATION
Private key: 4b8d7c3f2e1a9b5d8c6f4a2b1e9d7c5a3f1b9d7e5c3a1f8b6d4c2a1e9d7c5a
Public key (compressed): 0298e4c7f5b8a3d2c1f9e6d4b2a1c9f7e5d3b1a9f8e6d4c2b1a9f7e5d3bcf4
SIGNING
Message: Hello, secp256k1!
Message hash: 8c3d9e5f7b2a4c6d8e1f3a5b7c9d1e3f5a7b9c1d3e5f7a9b1c3d5e7f9a1b3c5d
Signature: 3045022100ab3c5d7e9f1a2b4c6d8e0f2a4c6d8e0f1a3b5c7d9e1f3a5b7c9d0221...
VERIFICATION
Signature valid: True
6. Real-World Applications
🪙 Cryptocurrency Wallets
Bitcoin & Ethereum Architecture:
- Private key (
d) → kept secret in your wallet - Public key (
Q = d·G) → derived from private key - Address → hash of public key (visible on blockchain)
- Transactions → signed with ECDSA using secp256k1
Private Key → Public Key → Hash → Address
(d) (Q = d·G) (SHA256) (visible)
🔗 Blockchain Consensus
- Transaction Validation: Nodes verify signatures to ensure transactions are authorized
- Message Authentication: Proves that messages come from the holder of the private key
- Non-repudiation: Signers cannot deny creating valid signatures
✓ Use established libraries (don't roll your own crypto) ✓ Generate keys from high-entropy sources ✓ Implement proper key rotation policies ✓ Use deterministic nonce generation (RFC 6979) ✓ Validate all inputs during verification
Further Reading
- SEC 2: Recommended Elliptic Curve Domain Parameters
- RFC 6979: Deterministic Usage of DSA and ECDSA
- Bitcoin Developer Guide - Transactions
- Mastering Bitcoin by Andreas Antonopoulos