yaklang/hack-skills1 file

Lattice Crypto Attacks

>-

Specification
Skill ID
yaklang/hack-skills/lattice-crypto-attacks
Publisher
yaklang
Repository
hack-skills
Installs
0
Files
1
Synced
Sep 23, 2026
How to use it

Open any RiverX project, open the Skills panel in the chat, and search for this identifier. The files are fetched from the source repository at install time.

yaklang/hack-skills/lattice-crypto-attacksInstalls these files
  • SKILL.md

What this skill tells the agent

SKILL: Lattice-Based Cryptanalysis — Expert Attack Playbook

AI LOAD INSTRUCTION: Expert lattice techniques for CTF and cryptanalysis. Covers LLL/BKZ reduction, Coppersmith's method (univariate and multivariate), Hidden Number Problem for DSA/ECDSA nonce recovery, knapsack attacks, and NTRU analysis. Base models often fail to construct the correct attack lattice (wrong dimensions, missing scaling factors) or misapply Coppersmith bounds.

0. RELATED ROUTING

  • rsa-attack-techniques for RSA-specific attacks that use lattice methods (Coppersmith, Boneh-Durfee)
  • symmetric-cipher-attacks for LCG state recovery via lattice
  • classical-cipher-analysis when lattice methods apply to classical cipher analysis

Quick application guide

Problem TypeLattice TechniqueKey Parameter
RSA small rootsCoppersmith (LLL on polynomial lattice)Root bound X < N^(1/e)
RSA small dBoneh-Durfee (multivariate Coppersmith)d < N^0.292
DSA/ECDSA nonce biasHidden Number Problem → CVPBias bits known
Knapsack cipherLow-density lattice attackDensity < 0.9408
LCG truncated outputCVP on recurrence latticeUnknown bits per output
Subset sumLLL reduction on knapsack latticeElement size vs count
NTRU key recoveryLattice reduction on NTRU latticeDimension and key size

1. LATTICE FUNDAMENTALS

1.1 Definitions

A lattice L is the set of all integer linear combinations of basis vectors:

L = { a₁·b₁ + a₂·b₂ + ... + aₙ·bₙ | aᵢ ∈ ℤ }

where b₁, ..., bₙ are linearly independent vectors in ℝᵐ.

Key problems:

  • SVP (Shortest Vector Problem): Find the shortest non-zero vector in L
  • CVP (Closest Vector Problem): Given target t, find v ∈ L closest to t
  • SVP is NP-hard in general, but LLL finds an approximately short vector in polynomial time

1.2 Lattice Quality Metrics

Determinant: det(L) = |det(B)| where B is the basis matrix
Gaussian heuristic: shortest vector ≈ √(n/(2πe)) · det(L)^(1/n)

2. LLL ALGORITHM

2.1 What LLL Does

Takes a lattice basis B and produces a reduced basis B' where:

  • Vectors are nearly orthogonal
  • First vector is approximately short (within 2^((n-1)/2) factor of SVP)
  • Runs in polynomial time: O(n^5 · d · log³ B) where d = dimension, B = max entry size

2.2 SageMath Usage

# SageMath
M = matrix(ZZ, [
    [1, 0, 0, large_value_1],
    [0, 1, 0, large_value_2],
    [0, 0, 1, large_value_3],
    [0, 0, 0, modulus],
])

L = M.LLL()
# Short vectors in L reveal the solution
short_vector = L[0]  # first row is typically shortest

2.3 Python (fpylll)

from fpylll import IntegerMatrix, LLL

n = 4
A = IntegerMatrix(n, n)
# Fill matrix A...
A[0] = (1, 0, 0, large_value_1)
A[1] = (0, 1, 0, large_value_2)
A[2] = (0, 0, 1, large_value_3)
A[3] = (0, 0, 0, modulus)

LLL.reduction(A)
print(A[0])  # shortest vector

3. BKZ (BLOCK KORKINE-ZOLOTAREV)

3.1 Comparison with LLL

PropertyLLLBKZ-β
Quality2^((n-1)/2) approximation2^(n/(β-1)) approximation
SpeedPolynomialExponential in β
Block sizeFixed (2)Configurable β
Best forQuick reductionHigh-quality reduction

3.2 Usage

# SageMath
M = matrix(ZZ, [...])
L = M.BKZ(block_size=20)  # β = 20

# fpylll
from fpylll import BKZ
BKZ.reduction(A, BKZ.Param(block_size=20))

Rule of thumb: start with LLL, increase to BKZ if needed. BKZ block size 20-40 is usually sufficient for CTF.


4. COPPERSMITH'S METHOD

4.1 Univariate Case

Given f(x) ≡ 0 (mod N) with small root |x₀| < X, find x₀.

Bound: X < N^(1/d) where d = degree of f.

# SageMath — built-in small_roots
N = ...
R.<x> = PolynomialRing(Zmod(N))
f = x^3 + a*x^2 + b*x + c  # known polynomial
roots = f.small_roots(X=2^100, beta=1.0, epsilon=1/30)

Parameters:

  • X: upper bound on the root
  • beta: N = p^beta (beta=1.0 for modular root of N itself; beta=0.5 for root mod unknown factor p ≈ √N)
  • epsilon: smaller = better results but slower (try 1/30 to 1/100)

4.2 Stereotyped Message Attack (RSA)

# SageMath
n, e, c = ...  # RSA parameters
known_msb = ...  # known upper portion of message

R.<x> = PolynomialRing(Zmod(n))
f = (known_msb + x)^e - c

# x represents the unknown lower bits
X = 2^(unknown_bit_count)
roots = f.small_roots(X=X, beta=1.0)
if roots:
    m = known_msb + int(roots[0])

4.3 Partial Key Exposure (Factor p)

Known MSBs of p: p = p_known + x where x is small.

# SageMath
n = ...
p_known = ...  # known upper bits of p

R.<x> = PolynomialRing(Zmod(n))
f = p_known + x
roots = f.small_roots(X=2^unknown_bits, beta=0.5)
# beta=0.5 because p ≈ √n
if roots:
    p = p_known + int(roots[0])
    q = n // p

4.4 Multivariate Coppersmith (Howgrave-Graham)

For f(x, y) ≡ 0 (mod N):

  • No polynomial-time algorithm guaranteed
  • Heuristic methods work in practice
  • Used in Boneh-Durfee for RSA small d
# SageMath — Boneh-Durfee
# e*d ≡ 1 (mod phi) where phi = (p-1)(q-1)
# Rewrite: e*d = 1 + k*((n+1) - (p+q))
# Let x = k, y = (p+q), both small relative to n

R.<x, y> = PolynomialRing(ZZ)
A = (n + 1) // 2
f = 1 + x * (A + y)  # mod e

# Build shift polynomials and construct lattice
# Apply LLL to find small (x₀, y₀)

5. HIDDEN NUMBER PROBLEM (HNP) — DSA/ECDSA NONCE RECOVERY

5.1 Problem Statement

Given: signatures (rᵢ, sᵢ) where nonces kᵢ have known bias (leaked MSBs or LSBs).

DSA equation: s = k⁻¹(H(m) + xr) mod q

Rearranged: k = s⁻¹(H(m) + xr) mod q

If partial bits of k are known: reduces to CVP on a lattice.

5.2 Attack Setup

# SageMath
def ecdsa_nonce_attack(signatures, q, known_bits, bit_position='msb'):
    """
    signatures: list of (r, s, hash, known_nonce_bits)
    q: curve order
    known_bits: number of known bits per nonce
    """
    n = len(signatures)

    # Build lattice
    B = 2^(q.nbits() - known_bits)  # bound on unknown part
    M = matrix(QQ, n + 2, n + 2)

    for i in range(n):
        r_i, s_i, h_i, a_i = signatures[i]
        t_i = Integer(inverse_mod(s_i, q) * r_i % q)
        u_i = Integer(inverse_mod(s_i, q) * h_i % q)

        M[i, i] = q
        M[n, i] = t_i
        M[n+1, i] = u_i - a_i  # a_i = known nonce bits

    M[n, n] = B / q
    M[n+1, n+1] = B

    # LLL reduction
    L = M.LLL()

    # Find row containing the private key x
    for row in L:
        x_candidate = Integer(row[n] * q / B) % q
        # Verify x_candidate against one signature
        if verify_private_key(x_candidate, signatures[0], q):
            return x_candidate

    return None

5.3 Practical Nonce Bias Sources

SourceLeaked BitsRequired Signatures
MSB bias (always 0)1 bit~100 signatures
k generated with wrong lengthVariable~50 signatures
Timing side channel1-4 bits20-100 signatures
Insecure PRNGManyFew
Reused nonce (k₁ = k₂)All2 signatures

For reused nonce (simplest case):

def ecdsa_reused_nonce(r, s1, s2, h1, h2, q):
    """Recover private key when nonce k is reused."""
    # s1 - s2 = k⁻¹(h1 - h2) mod q  (since r is same)
    k = ((h1 - h2) * inverse_mod(s1 - s2, q)) % q
    x = ((s1 * k - h1) * inverse_mod(r, q)) % q
    return x, k

6. KNAPSACK / SUBSET SUM ATTACKS

6.1 Low-Density Attack

Knapsack: given weights a₁,...,aₙ and target S, find x₁,...,xₙ ∈ {0,1} such that Σxᵢaᵢ = S.

Density d = n / max(log₂ aᵢ). If d < 0.9408, lattice attack works.

# SageMath
def knapsack_lattice(weights, target):
    """Solve subset sum via LLL lattice attack."""
    n = len(weights)

    # Build lattice (Lagarias-Odlyzko style)
    N = ceil(sqrt(n) / 2)  # scaling factor
    M = matrix(ZZ, n + 1, n + 1)

    for i in range(n):

Use this skill in a project

Open any RiverX project, search the Skills panel for yaklang/hack-skills/lattice-crypto-attacks, and install it in one click.

Use this skill