Add foundational resources for elliptic curve operations and distributed systems

Added detailed pseudocode for elliptic curve algorithms covering modular arithmetic, point operations, scalar multiplication, and coordinate conversions. Also introduced a comprehensive knowledge base for distributed systems, including CAP theorem, consistency models, consensus protocols (e.g., Paxos, Raft, PBFT, Nakamoto), and fault-tolerant design principles.
This commit is contained in:
2025-12-02 19:14:39 +00:00
parent feae79af1a
commit 3c17e975df
8 changed files with 3705 additions and 1 deletions

View File

@@ -0,0 +1,369 @@
---
name: elliptic-curves
description: This skill should be used when working with elliptic curve cryptography, implementing or debugging secp256k1 operations, understanding modular arithmetic and finite fields, or implementing signature schemes like ECDSA and Schnorr. Provides comprehensive knowledge of group theory foundations, curve mathematics, point multiplication algorithms, and cryptographic optimizations.
---
# Elliptic Curve Cryptography
This skill provides deep knowledge of elliptic curve cryptography (ECC), with particular focus on the secp256k1 curve used in Bitcoin and Nostr, including the mathematical foundations and implementation considerations.
## When to Use This Skill
- Implementing or debugging elliptic curve operations
- Working with secp256k1, ECDSA, or Schnorr signatures
- Understanding modular arithmetic and finite field operations
- Optimizing cryptographic code for performance
- Analyzing security properties of curve-based cryptography
## Mathematical Foundations
### Groups in Cryptography
A **group** is a set G with a binary operation (often denoted · or +) satisfying:
1. **Closure**: For all a, b ∈ G, the result a · b is also in G
2. **Associativity**: (a · b) · c = a · (b · c)
3. **Identity**: There exists e ∈ G such that e · a = a · e = a
4. **Inverse**: For each a ∈ G, there exists a⁻¹ such that a · a⁻¹ = e
A **cyclic group** is generated by repeatedly applying the operation to a single element (the generator). The **order** of a group is the number of elements.
**Why groups matter in cryptography**: The discrete logarithm problem—given g and gⁿ, find n—is computationally hard in certain groups, forming the security basis for ECC.
### Modular Arithmetic
Modular arithmetic constrains calculations to a finite range [0, p-1] for some modulus p:
```
a ≡ b (mod p) means p divides (a - b)
Operations:
- Addition: (a + b) mod p
- Subtraction: (a - b + p) mod p
- Multiplication: (a × b) mod p
- Inverse: a⁻¹ where (a × a⁻¹) ≡ 1 (mod p)
```
**Computing modular inverse**:
- **Fermat's Little Theorem**: If p is prime, a⁻¹ ≡ a^(p-2) (mod p)
- **Extended Euclidean Algorithm**: More efficient for general cases
- **SafeGCD Algorithm**: Constant-time, used in libsecp256k1
### Finite Fields (Galois Fields)
A **finite field** GF(p) or 𝔽ₚ is a field with a finite number of elements where:
- p must be prime (or a prime power for extension fields)
- All arithmetic operations are defined and produce elements within the field
- Every non-zero element has a multiplicative inverse
For cryptographic curves like secp256k1, the field is 𝔽ₚ where p is a 256-bit prime.
**Key property**: The non-zero elements of a finite field form a cyclic group under multiplication.
## Elliptic Curves
### The Curve Equation
An elliptic curve over a finite field 𝔽ₚ is defined by the Weierstrass equation:
```
y² = x³ + ax + b (mod p)
```
The curve must satisfy the non-singularity condition: 4a³ + 27b² ≠ 0
### Points on the Curve
A point P = (x, y) is on the curve if it satisfies the equation. The set of all points, plus a special "point at infinity" O (the identity element), forms an abelian group.
### Point Operations
**Point Addition (P + Q where P ≠ Q)**:
```
λ = (y₂ - y₁) / (x₂ - x₁) (mod p)
x₃ = λ² - x₁ - x₂ (mod p)
y₃ = λ(x₁ - x₃) - y₁ (mod p)
```
**Point Doubling (P + P = 2P)**:
```
λ = (3x₁² + a) / (2y₁) (mod p)
x₃ = λ² - 2x₁ (mod p)
y₃ = λ(x₁ - x₃) - y₁ (mod p)
```
**Point at Infinity**: Acts as the identity element; P + O = P for all P.
**Point Negation**: -P = (x, -y) = (x, p - y)
## The secp256k1 Curve
### Parameters
secp256k1 is defined by SECG (Standards for Efficient Cryptography Group):
```
Curve equation: y² = x³ + 7 (a = 0, b = 7)
Prime modulus p:
0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F
= 2²⁵⁶ - 2³² - 977
Group order n:
0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141
Generator point G:
Gx = 0x79BE667E F9DCBBAC 55A06295 CE870B07 029BFCDB 2DCE28D9 59F2815B 16F81798
Gy = 0x483ADA77 26A3C465 5DA4FBFC 0E1108A8 FD17B448 A6855419 9C47D08F FB10D4B8
Cofactor h = 1
```
### Why secp256k1?
1. **Koblitz curve**: a = 0 enables faster computation (no ax term)
2. **Special prime**: p = 2²⁵⁶ - 2³² - 977 allows efficient modular reduction
3. **Deterministic construction**: Not randomly generated, reducing backdoor concerns
4. **~30% faster** than random curves when fully optimized
### Efficient Modular Reduction
The special form of p enables fast reduction without general division:
```
For p = 2²⁵⁶ - 2³² - 977:
To reduce a 512-bit number c = c_high × 2²⁵⁶ + c_low:
c ≡ c_low + c_high × 2³² + c_high × 977 (mod p)
```
## Point Multiplication Algorithms
Scalar multiplication kP (computing P + P + ... + P, k times) is the core operation.
### Double-and-Add (Binary Method)
```
Input: k (scalar), P (point)
Output: kP
R = O (point at infinity)
for i from bit_length(k)-1 down to 0:
R = 2R # Point doubling
if bit i of k is 1:
R = R + P # Point addition
return R
```
**Complexity**: O(log k) point operations
**Vulnerability**: Timing side-channels (different branches for 0/1 bits)
### Montgomery Ladder
Constant-time algorithm that performs the same operations regardless of bit values:
```
Input: k (scalar), P (point)
Output: kP
R0 = O
R1 = P
for i from bit_length(k)-1 down to 0:
if bit i of k is 0:
R1 = R0 + R1
R0 = 2R0
else:
R0 = R0 + R1
R1 = 2R1
return R0
```
**Advantage**: Resistant to simple power analysis and timing attacks.
### Window Methods (w-NAF)
Precompute small multiples of P, then process w bits at a time:
```
w-NAF representation reduces additions by ~1/3 compared to binary
Precomputation table: [P, 3P, 5P, 7P, ...] for w=4
```
### Endomorphism Optimization (GLV Method)
secp256k1 has an efficiently computable endomorphism φ where:
```
φ(x, y) = (βx, y) where β³ ≡ 1 (mod p)
φ(P) = λP where λ³ ≡ 1 (mod n)
```
This allows splitting scalar k into k₁ + k₂λ with smaller k₁, k₂, reducing operations by ~33-50%.
### Multi-Scalar Multiplication (Strauss-Shamir)
For computing k₁P₁ + k₂P₂ (common in signature verification):
```
Process both scalars simultaneously, combining operations
Reduces work compared to separate multiplications
```
## Coordinate Systems
### Affine Coordinates
Standard (x, y) representation. Requires modular inversion for each operation.
### Projective Coordinates
Represent (X:Y:Z) where x = X/Z, y = Y/Z:
- Avoids inversions during intermediate computations
- Only one inversion at the end to convert back to affine
### Jacobian Coordinates
Represent (X:Y:Z) where x = X/Z², y = Y/Z³:
- Fastest for point doubling
- Used extensively in libsecp256k1
### López-Dahab Coordinates
For curves over GF(2ⁿ), optimized for binary field arithmetic.
## Signature Schemes
### ECDSA (Elliptic Curve Digital Signature Algorithm)
**Key Generation**:
```
Private key: d (random integer in [1, n-1])
Public key: Q = dG
```
**Signing message m**:
```
1. Hash: e = H(m) truncated to curve order bit length
2. Random: k ∈ [1, n-1]
3. Compute: (x, y) = kG
4. Calculate: r = x mod n (if r = 0, restart with new k)
5. Calculate: s = k⁻¹(e + rd) mod n (if s = 0, restart)
6. Signature: (r, s)
```
**Verification of signature (r, s) on message m**:
```
1. Check: r, s ∈ [1, n-1]
2. Hash: e = H(m)
3. Compute: w = s⁻¹ mod n
4. Compute: u₁ = ew mod n, u₂ = rw mod n
5. Compute: (x, y) = u₁G + u₂Q
6. Valid if: r ≡ x (mod n)
```
**Security considerations**:
- k MUST be unique per signature (reuse leaks private key)
- Use RFC 6979 for deterministic k derivation
### Schnorr Signatures (BIP-340)
Simpler, more efficient, with provable security.
**Signing message m**:
```
1. Random: k ∈ [1, n-1]
2. Compute: R = kG
3. Challenge: e = H(R || Q || m)
4. Response: s = k + ed mod n
5. Signature: (R, s) or (r_x, s) where r_x is x-coordinate of R
```
**Verification**:
```
1. Compute: e = H(R || Q || m)
2. Check: sG = R + eQ
```
**Advantages over ECDSA**:
- Linear: enables signature aggregation (MuSig)
- Simpler verification (no modular inverse)
- Batch verification support
- Provably secure in Random Oracle Model
## Implementation Considerations
### Constant-Time Operations
To prevent timing attacks:
- Avoid branches dependent on secret data
- Use constant-time comparison functions
- Mask operations to hide data-dependent timing
```go
// BAD: Timing leak
if secretBit == 1 {
doOperation()
}
// GOOD: Constant-time conditional
result = conditionalSelect(secretBit, value1, value0)
```
### Memory Safety
- Zeroize sensitive data after use
- Avoid leaving secrets in registers or cache
- Use secure memory allocation when available
### Side-Channel Protections
- **Timing attacks**: Use constant-time algorithms
- **Power analysis**: Montgomery ladder, point blinding
- **Cache attacks**: Avoid table lookups indexed by secrets
### Random Number Generation
- Use cryptographically secure RNG for k in ECDSA
- Consider deterministic k (RFC 6979) for reproducibility
- Validate output is in valid range [1, n-1]
## libsecp256k1 Optimizations
The Bitcoin Core library includes:
1. **Field arithmetic**: 5×52-bit limbs for 64-bit platforms
2. **Scalar arithmetic**: 4×64-bit representation
3. **Endomorphism**: GLV decomposition enabled by default
4. **Batch inversion**: Amortizes expensive inversions
5. **SafeGCD**: Constant-time modular inverse
6. **Precomputed tables**: For generator point multiplications
## Security Properties
### Discrete Logarithm Problem (DLP)
Given P and Q = kP, finding k is computationally infeasible.
**Best known attacks**:
- Generic: Baby-step Giant-step, Pollard's rho: O(√n) operations
- For secp256k1: ~2¹²⁸ operations (128-bit security)
### Curve Security Criteria
- Large prime order subgroup
- Cofactor 1 (no small subgroup attacks)
- Resistant to MOV attack (embedding degree)
- Not anomalous (n ≠ p)
## Common Pitfalls
1. **k reuse in ECDSA**: Immediately leaks private key
2. **Weak random k**: Partially leaks key over multiple signatures
3. **Invalid curve points**: Validate points are on curve
4. **Small subgroup attacks**: Check point order (cofactor = 1 helps)
5. **Timing leaks**: Non-constant-time scalar multiplication
## References
For detailed implementations, see:
- `references/secp256k1-parameters.md` - Full curve parameters
- `references/algorithms.md` - Detailed algorithm pseudocode
- `references/security.md` - Security analysis and attack vectors

View File

@@ -0,0 +1,513 @@
# Elliptic Curve Algorithms
Detailed pseudocode for core elliptic curve operations.
## Field Arithmetic
### Modular Addition
```
function mod_add(a, b, p):
result = a + b
if result >= p:
result = result - p
return result
```
### Modular Subtraction
```
function mod_sub(a, b, p):
if a >= b:
return a - b
else:
return p - b + a
```
### Modular Multiplication
For general case:
```
function mod_mul(a, b, p):
return (a * b) mod p
```
For secp256k1 optimized (Barrett reduction):
```
function mod_mul_secp256k1(a, b):
# Compute full 512-bit product
product = a * b
# Split into high and low 256-bit parts
low = product & ((1 << 256) - 1)
high = product >> 256
# Reduce: result ≡ low + high * (2³² + 977) (mod p)
result = low + high * (1 << 32) + high * 977
# May need additional reduction
while result >= p:
result = result - p
return result
```
### Modular Inverse
**Extended Euclidean Algorithm**:
```
function mod_inverse(a, p):
if a == 0:
error "No inverse exists for 0"
old_r, r = p, a
old_s, s = 0, 1
while r != 0:
quotient = old_r / r
old_r, r = r, old_r - quotient * r
old_s, s = s, old_s - quotient * s
if old_r != 1:
error "No inverse exists"
if old_s < 0:
old_s = old_s + p
return old_s
```
**Fermat's Little Theorem** (for prime p):
```
function mod_inverse_fermat(a, p):
return mod_exp(a, p - 2, p)
```
### Modular Exponentiation (Square-and-Multiply)
```
function mod_exp(base, exp, p):
result = 1
base = base mod p
while exp > 0:
if exp & 1: # exp is odd
result = (result * base) mod p
exp = exp >> 1
base = (base * base) mod p
return result
```
### Modular Square Root (Tonelli-Shanks)
For secp256k1 where p ≡ 3 (mod 4):
```
function mod_sqrt(a, p):
# For p ≡ 3 (mod 4), sqrt(a) = a^((p+1)/4)
return mod_exp(a, (p + 1) / 4, p)
```
## Point Operations
### Point Validation
```
function is_on_curve(P, a, b, p):
if P is infinity:
return true
x, y = P
left = (y * y) mod p
right = (x * x * x + a * x + b) mod p
return left == right
```
### Point Addition (Affine Coordinates)
```
function point_add(P, Q, a, p):
if P is infinity:
return Q
if Q is infinity:
return P
x1, y1 = P
x2, y2 = Q
if x1 == x2:
if y1 == mod_neg(y2, p): # P = -Q
return infinity
else: # P == Q
return point_double(P, a, p)
# λ = (y2 - y1) / (x2 - x1)
numerator = mod_sub(y2, y1, p)
denominator = mod_sub(x2, x1, p)
λ = mod_mul(numerator, mod_inverse(denominator, p), p)
# x3 = λ² - x1 - x2
x3 = mod_sub(mod_sub(mod_mul(λ, λ, p), x1, p), x2, p)
# y3 = λ(x1 - x3) - y1
y3 = mod_sub(mod_mul(λ, mod_sub(x1, x3, p), p), y1, p)
return (x3, y3)
```
### Point Doubling (Affine Coordinates)
```
function point_double(P, a, p):
if P is infinity:
return infinity
x, y = P
if y == 0:
return infinity
# λ = (3x² + a) / (2y)
numerator = mod_add(mod_mul(3, mod_mul(x, x, p), p), a, p)
denominator = mod_mul(2, y, p)
λ = mod_mul(numerator, mod_inverse(denominator, p), p)
# x3 = λ² - 2x
x3 = mod_sub(mod_mul(λ, λ, p), mod_mul(2, x, p), p)
# y3 = λ(x - x3) - y
y3 = mod_sub(mod_mul(λ, mod_sub(x, x3, p), p), y, p)
return (x3, y3)
```
### Point Negation
```
function point_negate(P, p):
if P is infinity:
return infinity
x, y = P
return (x, p - y)
```
## Scalar Multiplication
### Double-and-Add (Left-to-Right)
```
function scalar_mult_double_add(k, P, a, p):
if k == 0 or P is infinity:
return infinity
if k < 0:
k = -k
P = point_negate(P, p)
R = infinity
bits = binary_representation(k) # MSB first
for bit in bits:
R = point_double(R, a, p)
if bit == 1:
R = point_add(R, P, a, p)
return R
```
### Montgomery Ladder (Constant-Time)
```
function scalar_mult_montgomery(k, P, a, p):
R0 = infinity
R1 = P
bits = binary_representation(k) # MSB first
for bit in bits:
if bit == 0:
R1 = point_add(R0, R1, a, p)
R0 = point_double(R0, a, p)
else:
R0 = point_add(R0, R1, a, p)
R1 = point_double(R1, a, p)
return R0
```
### w-NAF Scalar Multiplication
```
function compute_wNAF(k, w):
# Convert scalar to width-w Non-Adjacent Form
naf = []
while k > 0:
if k & 1: # k is odd
# Get w-bit window
digit = k mod (1 << w)
if digit >= (1 << (w-1)):
digit = digit - (1 << w)
naf.append(digit)
k = k - digit
else:
naf.append(0)
k = k >> 1
return naf
function scalar_mult_wNAF(k, P, w, a, p):
# Precompute odd multiples: [P, 3P, 5P, ..., (2^(w-1)-1)P]
precomp = [P]
P2 = point_double(P, a, p)
for i in range(1, 1 << (w-1)):
precomp.append(point_add(precomp[-1], P2, a, p))
# Convert k to w-NAF
naf = compute_wNAF(k, w)
# Compute scalar multiplication
R = infinity
for i in range(len(naf) - 1, -1, -1):
R = point_double(R, a, p)
digit = naf[i]
if digit > 0:
R = point_add(R, precomp[(digit - 1) / 2], a, p)
elif digit < 0:
R = point_add(R, point_negate(precomp[(-digit - 1) / 2], p), a, p)
return R
```
### Shamir's Trick (Multi-Scalar)
For computing k₁P + k₂Q efficiently:
```
function multi_scalar_mult(k1, P, k2, Q, a, p):
# Precompute P + Q
PQ = point_add(P, Q, a, p)
# Get binary representations (same length, padded)
bits1 = binary_representation(k1)
bits2 = binary_representation(k2)
max_len = max(len(bits1), len(bits2))
bits1 = pad_left(bits1, max_len)
bits2 = pad_left(bits2, max_len)
R = infinity
for i in range(max_len):
R = point_double(R, a, p)
b1, b2 = bits1[i], bits2[i]
if b1 == 1 and b2 == 1:
R = point_add(R, PQ, a, p)
elif b1 == 1:
R = point_add(R, P, a, p)
elif b2 == 1:
R = point_add(R, Q, a, p)
return R
```
## Jacobian Coordinates
More efficient for repeated operations.
### Conversion
```
# Affine to Jacobian
function affine_to_jacobian(P):
if P is infinity:
return (1, 1, 0) # Jacobian infinity
x, y = P
return (x, y, 1)
# Jacobian to Affine
function jacobian_to_affine(P, p):
X, Y, Z = P
if Z == 0:
return infinity
Z_inv = mod_inverse(Z, p)
Z_inv2 = mod_mul(Z_inv, Z_inv, p)
Z_inv3 = mod_mul(Z_inv2, Z_inv, p)
x = mod_mul(X, Z_inv2, p)
y = mod_mul(Y, Z_inv3, p)
return (x, y)
```
### Point Doubling (Jacobian)
For curve y² = x³ + 7 (a = 0):
```
function jacobian_double(P, p):
X, Y, Z = P
if Y == 0:
return (1, 1, 0) # infinity
# For a = 0: M = 3*X²
S = mod_mul(4, mod_mul(X, mod_mul(Y, Y, p), p), p)
M = mod_mul(3, mod_mul(X, X, p), p)
X3 = mod_sub(mod_mul(M, M, p), mod_mul(2, S, p), p)
Y3 = mod_sub(mod_mul(M, mod_sub(S, X3, p), p),
mod_mul(8, mod_mul(Y, Y, mod_mul(Y, Y, p), p), p), p)
Z3 = mod_mul(2, mod_mul(Y, Z, p), p)
return (X3, Y3, Z3)
```
### Point Addition (Jacobian + Affine)
Mixed addition is faster when one point is in affine:
```
function jacobian_add_affine(P, Q, p):
# P in Jacobian (X1, Y1, Z1), Q in affine (x2, y2)
X1, Y1, Z1 = P
x2, y2 = Q
if Z1 == 0:
return affine_to_jacobian(Q)
Z1Z1 = mod_mul(Z1, Z1, p)
U2 = mod_mul(x2, Z1Z1, p)
S2 = mod_mul(y2, mod_mul(Z1, Z1Z1, p), p)
H = mod_sub(U2, X1, p)
HH = mod_mul(H, H, p)
I = mod_mul(4, HH, p)
J = mod_mul(H, I, p)
r = mod_mul(2, mod_sub(S2, Y1, p), p)
V = mod_mul(X1, I, p)
X3 = mod_sub(mod_sub(mod_mul(r, r, p), J, p), mod_mul(2, V, p), p)
Y3 = mod_sub(mod_mul(r, mod_sub(V, X3, p), p), mod_mul(2, mod_mul(Y1, J, p), p), p)
Z3 = mod_mul(mod_sub(mod_mul(mod_add(Z1, H, p), mod_add(Z1, H, p), p),
mod_add(Z1Z1, HH, p), p), 1, p)
return (X3, Y3, Z3)
```
## GLV Endomorphism (secp256k1)
### Scalar Decomposition
```
# Constants for secp256k1
LAMBDA = 0x5363AD4CC05C30E0A5261C028812645A122E22EA20816678DF02967C1B23BD72
BETA = 0x7AE96A2B657C07106E64479EAC3434E99CF0497512F58995C1396C28719501EE
# Decomposition coefficients
A1 = 0x3086D221A7D46BCDE86C90E49284EB15
B1 = 0x114CA50F7A8E2F3F657C1108D9D44CFD8
A2 = 0xE4437ED6010E88286F547FA90ABFE4C3
B2 = A1
function glv_decompose(k, n):
# Compute c1 = round(b2 * k / n)
# Compute c2 = round(-b1 * k / n)
c1 = (B2 * k + n // 2) // n
c2 = (-B1 * k + n // 2) // n
# k1 = k - c1*A1 - c2*A2
# k2 = -c1*B1 - c2*B2
k1 = k - c1 * A1 - c2 * A2
k2 = -c1 * B1 - c2 * B2
return (k1, k2)
function glv_scalar_mult(k, P, p, n):
k1, k2 = glv_decompose(k, n)
# Compute endomorphism: φ(P) = (β*x, y)
x, y = P
phi_P = (mod_mul(BETA, x, p), y)
# Use Shamir's trick: k1*P + k2*φ(P)
return multi_scalar_mult(k1, P, k2, phi_P, 0, p)
```
## Batch Inversion
Amortize expensive inversions over multiple points:
```
function batch_invert(values, p):
n = len(values)
if n == 0:
return []
# Compute cumulative products
products = [values[0]]
for i in range(1, n):
products.append(mod_mul(products[-1], values[i], p))
# Invert the final product
inv = mod_inverse(products[-1], p)
# Compute individual inverses
inverses = [0] * n
for i in range(n - 1, 0, -1):
inverses[i] = mod_mul(inv, products[i - 1], p)
inv = mod_mul(inv, values[i], p)
inverses[0] = inv
return inverses
```
## Key Generation
```
function generate_keypair(G, n, p):
# Generate random private key
d = random_integer(1, n - 1)
# Compute public key
Q = scalar_mult(d, G)
return (d, Q)
```
## Point Compression/Decompression
```
function compress_point(P, p):
if P is infinity:
return bytes([0x00])
x, y = P
prefix = 0x02 if (y % 2 == 0) else 0x03
return bytes([prefix]) + x.to_bytes(32, 'big')
function decompress_point(compressed, a, b, p):
prefix = compressed[0]
if prefix == 0x00:
return infinity
x = int.from_bytes(compressed[1:], 'big')
# Compute y² = x³ + ax + b
y_squared = mod_add(mod_add(mod_mul(x, mod_mul(x, x, p), p),
mod_mul(a, x, p), p), b, p)
# Compute y = sqrt(y²)
y = mod_sqrt(y_squared, p)
# Select correct y based on prefix
if (prefix == 0x02) != (y % 2 == 0):
y = p - y
return (x, y)
```

View File

@@ -0,0 +1,194 @@
# secp256k1 Complete Parameters
## Curve Definition
**Name**: secp256k1 (Standards for Efficient Cryptography, prime field, 256-bit, Koblitz curve #1)
**Equation**: y² = x³ + 7 (mod p)
This is the short Weierstrass form with coefficients a = 0, b = 7.
## Field Parameters
### Prime Modulus p
```
Decimal:
115792089237316195423570985008687907853269984665640564039457584007908834671663
Hexadecimal:
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F
Binary representation:
2²⁵⁶ - 2³² - 2⁹ - 2⁸ - 2⁷ - 2⁶ - 2⁴ - 1
= 2²⁵⁶ - 2³² - 977
```
**Special form benefits**:
- Efficient modular reduction using: c mod p = c_low + c_high × (2³² + 977)
- Near-Mersenne prime enables fast arithmetic
### Group Order n
```
Decimal:
115792089237316195423570985008687907852837564279074904382605163141518161494337
Hexadecimal:
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
```
The number of points on the curve, including the point at infinity.
### Cofactor h
```
h = 1
```
Cofactor 1 means the group order n equals the curve order, simplifying security analysis and eliminating small subgroup attacks.
## Generator Point G
### Compressed Form
```
02 79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798
```
The 02 prefix indicates the y-coordinate is even.
### Uncompressed Form
```
04 79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798
483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8
```
### Individual Coordinates
**Gx**:
```
Decimal:
55066263022277343669578718895168534326250603453777594175500187360389116729240
Hexadecimal:
0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798
```
**Gy**:
```
Decimal:
32670510020758816978083085130507043184471273380659243275938904335757337482424
Hexadecimal:
0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8
```
## Endomorphism Parameters
secp256k1 has an efficiently computable endomorphism φ: (x, y) → (βx, y).
### β (Beta)
```
Hexadecimal:
0x7AE96A2B657C07106E64479EAC3434E99CF0497512F58995C1396C28719501EE
Property: β³ ≡ 1 (mod p)
```
### λ (Lambda)
```
Hexadecimal:
0x5363AD4CC05C30E0A5261C028812645A122E22EA20816678DF02967C1B23BD72
Property: λ³ ≡ 1 (mod n)
Relationship: φ(P) = λP for all points P
```
### GLV Decomposition Constants
For splitting scalar k into k₁ + k₂λ:
```
a₁ = 0x3086D221A7D46BCDE86C90E49284EB15
b₁ = -0xE4437ED6010E88286F547FA90ABFE4C3
a₂ = 0x114CA50F7A8E2F3F657C1108D9D44CFD8
b₂ = a₁
```
## Derived Constants
### Field Characteristics
```
(p + 1) / 4 = 0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFFF0C
Used for computing modular square roots via Tonelli-Shanks shortcut
```
### Order Characteristics
```
(n - 1) / 2 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0
Used in low-S normalization for ECDSA signatures
```
## Validation Formulas
### Point on Curve Check
For point (x, y), verify:
```
y² ≡ x³ + 7 (mod p)
```
### Generator Verification
Verify G is on curve:
```
Gy² mod p = 0x9C47D08FFB10D4B8 ... (truncated for display)
Gx³ + 7 mod p = same value
```
### Order Verification
Verify nG = O (point at infinity):
```
Computing n × G should yield the identity element
```
## Bit Lengths
| Parameter | Bits | Bytes |
|-----------|------|-------|
| p (prime) | 256 | 32 |
| n (order) | 256 | 32 |
| Private key | 256 | 32 |
| Public key (compressed) | 257 | 33 |
| Public key (uncompressed) | 513 | 65 |
| ECDSA signature | 512 | 64 |
| Schnorr signature | 512 | 64 |
## Security Level
- **Equivalent symmetric key strength**: 128 bits
- **Best known attack complexity**: ~2¹²⁸ operations (Pollard's rho)
- **Safe until**: Quantum computers with ~1500+ logical qubits
## ASN.1 OID
```
1.3.132.0.10
iso(1) identified-organization(3) certicom(132) curve(0) secp256k1(10)
```
## Comparison with Other Curves
| Curve | Field Size | Security | Speed | Use Case |
|-------|------------|----------|-------|----------|
| secp256k1 | 256-bit | 128-bit | Fast (Koblitz) | Bitcoin, Nostr |
| secp256r1 (P-256) | 256-bit | 128-bit | Moderate | TLS, general |
| Curve25519 | 255-bit | ~128-bit | Very fast | Modern crypto |
| secp384r1 (P-384) | 384-bit | 192-bit | Slower | High security |

View File

@@ -0,0 +1,291 @@
# Elliptic Curve Security Analysis
Security properties, attack vectors, and mitigations for elliptic curve cryptography.
## The Discrete Logarithm Problem (ECDLP)
### Definition
Given points P and Q = kP on an elliptic curve, find the scalar k.
**Security assumption**: For properly chosen curves, this problem is computationally infeasible.
### Best Known Attacks
#### Generic Attacks (Work on Any Group)
| Attack | Complexity | Notes |
|--------|------------|-------|
| Baby-step Giant-step | O(√n) space and time | Requires √n storage |
| Pollard's rho | O(√n) time, O(1) space | Practical for large groups |
| Pollard's lambda | O(√n) | When k is in known range |
| Pohlig-Hellman | O(√p) where p is largest prime factor | Exploits factorization of n |
For secp256k1 (n ≈ 2²⁵⁶):
- Generic attack complexity: ~2¹²⁸ operations
- Equivalent to 128-bit symmetric security
#### Curve-Specific Attacks
| Attack | Applicable When | Mitigation |
|--------|-----------------|------------|
| MOV/FR reduction | Low embedding degree | Use curves with high embedding degree |
| Anomalous curve attack | n = p | Ensure n ≠ p |
| GHS attack | Extension field curves | Use prime field curves |
**secp256k1 is immune to all known curve-specific attacks**.
## Side-Channel Attacks
### Timing Attacks
**Vulnerability**: Execution time varies based on secret data.
**Examples**:
- Conditional branches on secret bits
- Early exit conditions
- Variable-time modular operations
**Mitigations**:
- Constant-time algorithms (Montgomery ladder)
- Fixed execution paths
- Dummy operations to equalize timing
### Power Analysis
**Simple Power Analysis (SPA)**: Single trace reveals operations.
- Double-and-add visible as different power signatures
- Mitigation: Montgomery ladder (uniform operations)
**Differential Power Analysis (DPA)**: Statistical analysis of many traces.
- Mitigation: Point blinding, scalar blinding
### Cache Attacks
**FLUSH+RELOAD Attack**:
```
1. Attacker flushes cache line containing lookup table
2. Victim performs table lookup based on secret
3. Attacker measures reload time to determine which entry was accessed
```
**Mitigations**:
- Avoid secret-dependent table lookups
- Use constant-time table access patterns
- Scatter tables to prevent cache line sharing
### Electromagnetic (EM) Attacks
Similar to power analysis but captures electromagnetic emissions.
**Mitigations**:
- Shielding
- Same algorithmic protections as power analysis
## Implementation Vulnerabilities
### k-Reuse in ECDSA
**The Sony PS3 Hack (2010)**:
If the same k is used for two signatures (r₁, s₁) and (r₂, s₂) on messages m₁ and m₂:
```
s₁ = k⁻¹(e₁ + rd) mod n
s₂ = k⁻¹(e₂ + rd) mod n
Since k is the same:
s₁ - s₂ = k⁻¹(e₁ - e₂) mod n
k = (e₁ - e₂)(s₁ - s₂)⁻¹ mod n
Once k is known:
d = (s₁k - e₁)r⁻¹ mod n
```
**Mitigation**: Use deterministic k (RFC 6979).
### Weak Random k
Even with unique k values, if the RNG is biased:
- Lattice-based attacks can recover private key
- Only ~1% bias in k can be exploitable with enough signatures
**Mitigations**:
- Use cryptographically secure RNG
- Use deterministic k (RFC 6979)
- Verify k is in valid range [1, n-1]
### Invalid Curve Attacks
**Attack**: Attacker provides point not on the curve.
- Point may be on a weaker curve
- Operations may leak information
**Mitigation**: Always validate points are on curve:
```
Verify: y² ≡ x³ + ax + b (mod p)
```
### Small Subgroup Attacks
**Attack**: If cofactor h > 1, points of small order exist.
- Attacker sends point of small order
- Response reveals private key mod (small order)
**Mitigation**:
- Use curves with cofactor 1 (secp256k1 has h = 1)
- Multiply received points by cofactor
- Validate point order
### Fault Attacks
**Attack**: Induce computational errors (voltage glitches, radiation).
- Corrupted intermediate values may leak information
- Differential fault analysis can recover keys
**Mitigations**:
- Redundant computations with comparison
- Verify final results
- Hardware protections
## Signature Malleability
### ECDSA Malleability
Given valid signature (r, s), signature (r, n - s) is also valid for the same message.
**Impact**: Transaction ID malleability (historical Bitcoin issue)
**Mitigation**: Enforce low-S normalization:
```
if s > n/2:
s = n - s
```
### Schnorr Non-Malleability
BIP-340 Schnorr signatures are non-malleable by design:
- Use x-only public keys
- Deterministic nonce derivation
## Quantum Threats
### Shor's Algorithm
**Threat**: Polynomial-time discrete log on quantum computers.
- Requires ~1500-2000 logical qubits for secp256k1
- Current quantum computers: <100 noisy qubits
**Timeline**: Estimated 10-20+ years for cryptographically relevant quantum computers.
### Migration Strategy
1. **Monitor**: Track quantum computing progress
2. **Prepare**: Develop post-quantum alternatives
3. **Hybrid**: Use classical + post-quantum in transition
4. **Migrate**: Full transition when necessary
### Post-Quantum Alternatives
- Lattice-based signatures (CRYSTALS-Dilithium)
- Hash-based signatures (SPHINCS+)
- Code-based cryptography
## Best Practices
### Key Generation
```
DO:
- Use cryptographically secure RNG
- Validate private key is in [1, n-1]
- Verify public key is on curve
- Verify public key is not point at infinity
DON'T:
- Use predictable seeds
- Use truncated random values
- Skip validation
```
### Signature Generation
```
DO:
- Use RFC 6979 for deterministic k
- Validate all inputs
- Use constant-time operations
- Clear sensitive memory after use
DON'T:
- Reuse k values
- Use weak/biased RNG
- Skip low-S normalization (ECDSA)
```
### Signature Verification
```
DO:
- Validate r, s are in [1, n-1]
- Validate public key is on curve
- Validate public key is not infinity
- Use batch verification when possible
DON'T:
- Skip any validation steps
- Accept malformed signatures
```
### Public Key Handling
```
DO:
- Validate received points are on curve
- Check point is not infinity
- Prefer compressed format for storage
DON'T:
- Accept unvalidated points
- Skip curve membership check
```
## Security Checklist
### Implementation Review
- [ ] All scalar multiplications are constant-time
- [ ] No secret-dependent branches
- [ ] No secret-indexed table lookups
- [ ] Memory is zeroized after use
- [ ] Random k uses CSPRNG or RFC 6979
- [ ] All received points are validated
- [ ] Private keys are in valid range
- [ ] Signatures use low-S normalization
### Operational Security
- [ ] Private keys stored securely (HSM, secure enclave)
- [ ] Key derivation uses proper KDF
- [ ] Backups are encrypted
- [ ] Key rotation policy exists
- [ ] Audit logging enabled
- [ ] Incident response plan exists
## Security Levels Comparison
| Curve | Bits | Symmetric Equivalent | RSA Equivalent |
|-------|------|---------------------|----------------|
| secp192r1 | 192 | 96 | 1536 |
| secp224r1 | 224 | 112 | 2048 |
| secp256k1 | 256 | 128 | 3072 |
| secp384r1 | 384 | 192 | 7680 |
| secp521r1 | 521 | 256 | 15360 |
## References
- NIST SP 800-57: Recommendation for Key Management
- SEC 1: Elliptic Curve Cryptography
- RFC 6979: Deterministic Usage of DSA and ECDSA
- BIP-340: Schnorr Signatures for secp256k1
- SafeCurves: Choosing Safe Curves for Elliptic-Curve Cryptography