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:
513
.claude/skills/elliptic-curves/references/algorithms.md
Normal file
513
.claude/skills/elliptic-curves/references/algorithms.md
Normal 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)
|
||||
```
|
||||
@@ -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 |
|
||||
291
.claude/skills/elliptic-curves/references/security.md
Normal file
291
.claude/skills/elliptic-curves/references/security.md
Normal 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
|
||||
Reference in New Issue
Block a user