lattice-crypto-attacks
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSKILL: Lattice-Based Cryptanalysis — Expert Attack Playbook
SKILL:基于格的密码分析——专家攻击指南
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.
AI加载说明:适用于CTF和密码分析的专业格技术。涵盖LLL/BKZ规约、Coppersmith方法(单变量和多变量)、用于DSA/ECDSA随机数恢复的隐藏数问题、背包攻击以及NTRU分析。基础模型通常无法构建正确的攻击格(维度错误、缺少缩放因子)或者错误应用Coppersmith边界。
0. RELATED ROUTING
0. 相关导航
- 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
- rsa-attack-techniques 包含使用格方法的RSA专项攻击(Coppersmith、Boneh-Durfee)
- symmetric-cipher-attacks 包含通过格方法恢复LCG状态的内容
- classical-cipher-analysis 适用于格方法可应用于古典密码分析的场景
Quick application guide
快速应用指南
| Problem Type | Lattice Technique | Key Parameter |
|---|---|---|
| RSA small roots | Coppersmith (LLL on polynomial lattice) | Root bound X < N^(1/e) |
| RSA small d | Boneh-Durfee (multivariate Coppersmith) | d < N^0.292 |
| DSA/ECDSA nonce bias | Hidden Number Problem → CVP | Bias bits known |
| Knapsack cipher | Low-density lattice attack | Density < 0.9408 |
| LCG truncated output | CVP on recurrence lattice | Unknown bits per output |
| Subset sum | LLL reduction on knapsack lattice | Element size vs count |
| NTRU key recovery | Lattice reduction on NTRU lattice | Dimension and key size |
| 问题类型 | 格技术 | 关键参数 |
|---|---|---|
| RSA小根 | Coppersmith(多项式格上的LLL规约) | 根边界 X < N^(1/e) |
| RSA小私钥d | Boneh-Durfee(多变量Coppersmith) | d < N^0.292 |
| DSA/ECDSA随机数偏差 | 隐藏数问题 → CVP | 已知偏差比特数 |
| 背包密码 | 低密度格攻击 | 密度 < 0.9408 |
| LCG截断输出 | 递推格上的CVP | 每个输出的未知比特数 |
| 子集和 | 背包格上的LLL规约 | 元素大小与数量的关系 |
| NTRU密钥恢复 | NTRU格上的格规约 | 维度与密钥大小 |
1. LATTICE FUNDAMENTALS
1. 格基础
1.1 Definitions
1.1 定义
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
格 L 是基向量所有整数线性组合的集合:
L = { a₁·b₁ + a₂·b₂ + ... + aₙ·bₙ | aᵢ ∈ ℤ }其中 b₁, ..., bₙ 是 ℝᵐ 中的线性无关向量。
核心问题:
- SVP(最短向量问题):找到L中最短的非零向量
- CVP(最近向量问题):给定目标向量t,找到L中最接近t的向量v
- 一般情况下SVP是NP难问题,但LLL算法可以在多项式时间内找到近似最短向量
1.2 Lattice Quality Metrics
1.2 格质量指标
Determinant: det(L) = |det(B)| where B is the basis matrix
Gaussian heuristic: shortest vector ≈ √(n/(2πe)) · det(L)^(1/n)行列式: det(L) = |det(B)|,其中B是基矩阵
高斯启发式: 最短向量 ≈ √(n/(2πe)) · det(L)^(1/n)2. LLL ALGORITHM
2. LLL算法
2.1 What LLL Does
2.1 LLL的作用
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
接收格基B,生成规约基 B',满足:
- 向量几乎正交
- 第一个向量是近似最短向量(与SVP的误差在2^((n-1)/2)因子以内)
- 多项式时间运行:O(n^5 · d · log³ B),其中d是维度,B是矩阵元素最大值
2.2 SageMath Usage
2.2 SageMath使用示例
python
undefinedpython
undefinedSageMath
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()
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
L中的短向量对应解
short_vector = L[0] # first row is typically shortest
undefinedshort_vector = L[0] # 第一行通常是最短向量
undefined2.3 Python (fpylll)
2.3 Python(fpylll)使用示例
python
from fpylll import IntegerMatrix, LLL
n = 4
A = IntegerMatrix(n, n)python
from fpylll import IntegerMatrix, LLL
n = 4
A = IntegerMatrix(n, n)Fill matrix A...
填充矩阵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
---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]) # 最短向量
---3. BKZ (BLOCK KORKINE-ZOLOTAREV)
3. BKZ(BLOCK KORKINE-ZOLOTAREV)算法
3.1 Comparison with LLL
3.1 与LLL的对比
| Property | LLL | BKZ-β |
|---|---|---|
| Quality | 2^((n-1)/2) approximation | 2^(n/(β-1)) approximation |
| Speed | Polynomial | Exponential in β |
| Block size | Fixed (2) | Configurable β |
| Best for | Quick reduction | High-quality reduction |
| 属性 | LLL | BKZ-β |
|---|---|---|
| 规约质量 | 2^((n-1)/2) 近似比 | 2^(n/(β-1)) 近似比 |
| 速度 | 多项式时间 | 随β指数级增长 |
| 块大小 | 固定为2 | 可配置β |
| 适用场景 | 快速规约 | 高质量规约 |
3.2 Usage
3.2 使用示例
python
undefinedpython
undefinedSageMath
SageMath
M = matrix(ZZ, [...])
L = M.BKZ(block_size=20) # β = 20
M = matrix(ZZ, [...])
L = M.BKZ(block_size=20) # β = 20
fpylll
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.
---from fpylll import BKZ
BKZ.reduction(A, BKZ.Param(block_size=20))
经验法则:先使用LLL,若失败再升级为BKZ。CTF场景下BKZ块大小20-40通常足够。
---4. COPPERSMITH'S METHOD
4. COPPERSMITH方法
4.1 Univariate Case
4.1 单变量场景
Given f(x) ≡ 0 (mod N) with small root |x₀| < X, find x₀.
Bound: X < N^(1/d) where d = degree of f.
python
undefined给定f(x) ≡ 0 (mod N),存在小根 |x₀| < X,求解x₀。
边界:X < N^(1/d),其中d是f的次数。
python
undefinedSageMath — built-in small_roots
SageMath — 内置small_roots方法
N = ...
R.<x> = PolynomialRing(Zmod(N))
f = x^3 + ax^2 + bx + 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)N = ...
R.<x> = PolynomialRing(Zmod(N))
f = x^3 + ax^2 + bx + c # 已知多项式
roots = f.small_roots(X=2^100, beta=1.0, epsilon=1/30)
**参数说明**:
- `X`:根的上边界
- `beta`:N = p^beta(beta=1.0对应模N本身的根;beta=0.5对应模未知因子p ≈ √N的根)
- `epsilon`:值越小效果越好但速度越慢,建议取1/30到1/100之间4.2 Stereotyped Message Attack (RSA)
4.2 固定格式消息攻击(RSA)
python
undefinedpython
undefinedSageMath
SageMath
n, e, c = ... # RSA parameters
known_msb = ... # known upper portion of message
R.<x> = PolynomialRing(Zmod(n))
f = (known_msb + x)^e - c
n, e, c = ... # RSA参数
known_msb = ... # 消息已知的高位部分
R.<x> = PolynomialRing(Zmod(n))
f = (known_msb + x)^e - c
x represents the unknown lower bits
x代表未知的低位比特
X = 2^(unknown_bit_count)
roots = f.small_roots(X=X, beta=1.0)
if roots:
m = known_msb + int(roots[0])
undefinedX = 2^(unknown_bit_count)
roots = f.small_roots(X=X, beta=1.0)
if roots:
m = known_msb + int(roots[0])
undefined4.3 Partial Key Exposure (Factor p)
4.3 部分密钥泄露(分解p)
Known MSBs of p: where x is small.
p = p_known + xpython
undefined已知p的高位:,其中x很小。
p = p_known + xpython
undefinedSageMath
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)
n = ...
p_known = ... # 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
beta=0.5因为p ≈ √n
if roots:
p = p_known + int(roots[0])
q = n // p
undefinedif roots:
p = p_known + int(roots[0])
q = n // p
undefined4.4 Multivariate Coppersmith (Howgrave-Graham)
4.4 多变量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
python
undefined针对f(x, y) ≡ 0 (mod N)的场景:
- 没有保证多项式时间的算法
- 启发式方法在实践中有效
- 用于Boneh-Durfee算法破解RSA小私钥d
python
undefinedSageMath — Boneh-Durfee
SageMath — Boneh-Durfee
e*d ≡ 1 (mod phi) where phi = (p-1)(q-1)
e*d ≡ 1 (mod phi) 其中 phi = (p-1)(q-1)
Rewrite: ed = 1 + k((n+1) - (p+q))
重写为: ed = 1 + k((n+1) - (p+q))
Let x = k, y = (p+q), both small relative to n
令x = k, y = (p+q),二者都远小于n
R.<x, y> = PolynomialRing(ZZ)
A = (n + 1) // 2
f = 1 + x * (A + y) # mod e
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₀)
应用LLL寻找小根(x₀, y₀)
---
---5. HIDDEN NUMBER PROBLEM (HNP) — DSA/ECDSA NONCE RECOVERY
5. 隐藏数问题(HNP)—— DSA/ECDSA随机数恢复
5.1 Problem Statement
5.1 问题描述
Given: signatures (rᵢ, sᵢ) where nonces kᵢ have known bias (leaked MSBs or LSBs).
DSA equation:
s = k⁻¹(H(m) + xr) mod qRearranged:
k = s⁻¹(H(m) + xr) mod qIf partial bits of k are known: reduces to CVP on a lattice.
给定:签名(rᵢ, sᵢ),其中随机数kᵢ存在已知偏差(泄露高位或低位比特)。
DSA等式:
s = k⁻¹(H(m) + xr) mod q整理后:
k = s⁻¹(H(m) + xr) mod q如果k的部分比特已知:可归约为格上的CVP问题。
5.2 Attack Setup
5.2 攻击实现
python
undefinedpython
undefinedSageMath
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 Noneundefineddef ecdsa_nonce_attack(signatures, q, known_bits, bit_position='msb'):
"""
signatures: 签名列表,格式为(r, s, hash, known_nonce_bits)
q: 椭圆曲线阶
known_bits: 每个随机数的已知比特数
"""
n = len(signatures)
# 构建格
B = 2^(q.nbits() - known_bits) # 未知部分的边界
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 = 随机数已知比特
M[n, n] = B / q
M[n+1, n+1] = B
# LLL规约
L = M.LLL()
# 查找包含私钥x的行
for row in L:
x_candidate = Integer(row[n] * q / B) % q
# 用一个签名验证x候选值
if verify_private_key(x_candidate, signatures[0], q):
return x_candidate
return Noneundefined5.3 Practical Nonce Bias Sources
5.3 常见随机数偏差来源
| Source | Leaked Bits | Required Signatures |
|---|---|---|
| MSB bias (always 0) | 1 bit | ~100 signatures |
| k generated with wrong length | Variable | ~50 signatures |
| Timing side channel | 1-4 bits | 20-100 signatures |
| Insecure PRNG | Many | Few |
| Reused nonce (k₁ = k₂) | All | 2 signatures |
For reused nonce (simplest case):
python
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| 来源 | 泄露比特数 | 所需签名数量 |
|---|---|---|
| 高位偏差(恒为0) | 1比特 | ~100个签名 |
| k生成时长度错误 | 可变 | ~50个签名 |
| 计时侧信道 | 1-4比特 | 20-100个签名 |
| 不安全PRNG | 多比特 | 少量 |
| 随机数重用(k₁ = k₂) | 全部比特 | 2个签名 |
针对随机数重用(最简单场景):
python
def ecdsa_reused_nonce(r, s1, s2, h1, h2, q):
"""当随机数k重用时恢复私钥。"""
# s1 - s2 = k⁻¹(h1 - h2) mod q (因为r相同)
k = ((h1 - h2) * inverse_mod(s1 - s2, q)) % q
x = ((s1 * k - h1) * inverse_mod(r, q)) % q
return x, k6. KNAPSACK / SUBSET SUM ATTACKS
6. 背包/子集和攻击
6.1 Low-Density Attack
6.1 低密度攻击
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.
python
undefined背包问题:给定权重a₁,...,aₙ和目标S,寻找x₁,...,xₙ ∈ {0,1},满足Σxᵢaᵢ = S。
密度 d = n / max(log₂ aᵢ)。如果d < 0.9408,格攻击有效。
python
undefinedSageMath
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):
M[i, i] = 1
M[i, n] = N * weights[i]
M[n, n] = N * target
# Alternative: CJLOSS embedding
M2 = matrix(ZZ, n + 1, n + 2)
for i in range(n):
M2[i, i] = 1
M2[i, n + 1] = N * weights[i]
M2[n, n] = 1
M2[n, n + 1] = N * (-target)
L = M2.LLL()
# Look for short vector with entries in {0, 1, -1}
for row in L:
if all(v in (0, 1) for v in row[:n]):
solution = list(row[:n])
if sum(solution[i] * weights[i] for i in range(n)) == target:
return solution
return None
---def knapsack_lattice(weights, target):
"""通过LLL格攻击求解子集和问题。"""
n = len(weights)
# 构建格(Lagarias-Odlyzko风格)
N = ceil(sqrt(n) / 2) # 缩放因子
M = matrix(ZZ, n + 1, n + 1)
for i in range(n):
M[i, i] = 1
M[i, n] = N * weights[i]
M[n, n] = N * target
# 替代方案:CJLOSS嵌入
M2 = matrix(ZZ, n + 1, n + 2)
for i in range(n):
M2[i, i] = 1
M2[i, n + 1] = N * weights[i]
M2[n, n] = 1
M2[n, n + 1] = N * (-target)
L = M2.LLL()
# 查找元素为{0, 1, -1}的短向量
for row in L:
if all(v in (0, 1) for v in row[:n]):
solution = list(row[:n])
if sum(solution[i] * weights[i] for i in range(n)) == target:
return solution
return None
---7. NTRU CRYPTANALYSIS
7. NTRU密码分析
7.1 NTRU Lattice
7.1 NTRU格
python
undefinedpython
undefinedSageMath
SageMath
def ntru_lattice_attack(h, q, N):
"""
Construct NTRU lattice for key recovery.
h = public key polynomial (mod q)
q = modulus
N = dimension
"""
# NTRU lattice:
# | qI 0 |
# | H I |
# where H is the circulant matrix of h
H = matrix(ZZ, N, N)
for i in range(N):
for j in range(N):
H[i, j] = h[(j - i) % N]
M = block_matrix([
[q * identity_matrix(N), zero_matrix(N)],
[H, identity_matrix(N)]
])
L = M.LLL()
# Short vector in reduced basis = (f, g) private key
for row in L:
f = vector(row[:N])
g = vector(row[N:])
if f.norm() < q and g.norm() < q:
return f, g
return None
---def ntru_lattice_attack(h, q, N):
"""
构建NTRU格用于密钥恢复。
h = 公钥多项式(模q)
q = 模数
N = 维度
"""
# NTRU格:
# | qI 0 |
# | H I |
# 其中H是h的循环矩阵
H = matrix(ZZ, N, N)
for i in range(N):
for j in range(N):
H[i, j] = h[(j - i) % N]
M = block_matrix([
[q * identity_matrix(N), zero_matrix(N)],
[H, identity_matrix(N)]
])
L = M.LLL()
# 规约基中的短向量 = (f, g) 私钥
for row in L:
f = vector(row[:N])
g = vector(row[N:])
if f.norm() < q and g.norm() < q:
return f, g
return None
---8. CONSTRUCTING ATTACK LATTICES — METHODOLOGY
8. 攻击格构建方法
8.1 General Recipe
8.1 通用流程
1. Express the cryptographic problem as:
"Find small x such that f(x) ≡ 0 (mod N)"
or "Find x close to target t in some lattice L"
2. Choose lattice type:
├─ Polynomial lattice → Coppersmith-style
├─ Modular lattice → HNP-style CVP
└─ Knapsack lattice → subset sum / CJLOSS
3. Determine dimensions:
└─ More dimensions = better approximation but slower
4. Set scaling factors:
└─ Balance the rows so short vector has roughly equal entries
└─ Common: multiply by N/X where X is the root bound
5. Apply reduction:
├─ LLL first (fast, usually sufficient)
└─ BKZ if LLL fails (increase block size: 20, 30, 40)
6. Extract solution:
└─ Check reduced basis rows for valid solutions1. 将密码问题转化为以下形式:
"寻找小x满足f(x) ≡ 0 (mod N)"
或 "在格L中寻找接近目标t的x"
2. 选择格类型:
├─ 多项式格 → Coppersmith风格攻击
├─ 模块化格 → HNP风格CVP
└─ 背包格 → 子集和 / CJLOSS
3. 确定维度:
└─ 维度越高近似效果越好,但速度越慢
4. 设置缩放因子:
└─ 平衡行向量,使短向量的元素大小大致相当
└─ 通用方案:乘以N/X,其中X是根边界
5. 应用规约:
├─ 优先使用LLL(速度快,通常足够)
└─ 若LLL失败则使用BKZ(逐步增加块大小:20, 30, 40)
6. 提取解:
└─ 检查规约基的行是否为有效解8.2 Embedding Technique (CVP → SVP)
8.2 嵌入技术(CVP → SVP)
Transform CVP into SVP by embedding the target into the lattice:
python
undefined通过将目标向量嵌入格中,将CVP转化为SVP问题:
python
undefinedSageMath
SageMath
def cvp_to_svp(basis_matrix, target, scale=1):
"""Convert CVP to SVP via Kannan's embedding."""
n = basis_matrix.nrows()
m = basis_matrix.ncols()
# Augment matrix
M = matrix(ZZ, n + 1, m + 1)
for i in range(n):
for j in range(m):
M[i, j] = basis_matrix[i, j]
M[i, m] = 0
for j in range(m):
M[n, j] = target[j]
M[n, m] = scale # scaling factor (try 1, then adjust)
L = M.LLL()
# Look for row with last entry = ±scale
for row in L:
if abs(row[m]) == scale:
return vector(target) - vector(row[:m]) * (row[m] // abs(row[m]))
return Noneundefineddef cvp_to_svp(basis_matrix, target, scale=1):
"""通过Kannan嵌入将CVP转化为SVP。"""
n = basis_matrix.nrows()
m = basis_matrix.ncols()
# 扩展矩阵
M = matrix(ZZ, n + 1, m + 1)
for i in range(n):
for j in range(m):
M[i, j] = basis_matrix[i, j]
M[i, m] = 0
for j in range(m):
M[n, j] = target[j]
M[n, m] = scale # 缩放因子(先尝试1,再调整)
L = M.LLL()
# 查找最后一个元素为±scale的行
for row in L:
if abs(row[m]) == scale:
return vector(target) - vector(row[:m]) * (row[m] // abs(row[m]))
return Noneundefined8.3 Dimension Selection Guide
8.3 维度选择指南
| Problem | Typical Dimension | Notes |
|---|---|---|
| Coppersmith univariate (degree d) | d × m where m ≈ 1/ε | Larger m = smaller root bound |
| HNP with n signatures | n + 2 | n ≥ known_bits_ratio × q_bits |
| Knapsack with n weights | n + 1 or n + 2 | Depends on density |
| LCG with n outputs | n + 1 | More outputs = easier |
| Boneh-Durfee | (m+1)(m+2)/2 | m = parameter depth |
| 问题 | 典型维度 | 说明 |
|---|---|---|
| 单变量Coppersmith(次数d) | d × m,其中m ≈ 1/ε | m越大根边界越小 |
| 含n个签名的HNP | n + 2 | n ≥ 已知比特比例 × q的比特数 |
| 含n个权重的背包问题 | n + 1 或 n + 2 | 取决于密度 |
| 含n个输出的LCG | n + 1 | 输出越多越容易破解 |
| Boneh-Durfee | (m+1)(m+2)/2 | m是参数深度 |
9. DECISION TREE
9. 决策树
Lattice approach needed — which construction?
│
├─ RSA-related?
│ ├─ Small unknown part of message → Coppersmith univariate
│ │ └─ Check: unknown_bits < n_bits / e
│ ├─ Partial factor knowledge → Coppersmith mod p
│ │ └─ Use beta=0.5, X=2^unknown_bits
│ ├─ Small private exponent d → Boneh-Durfee
│ │ └─ Check: d < N^0.292
│ └─ Multiple related equations → multivariate Coppersmith
│
├─ DSA/ECDSA-related?
│ ├─ Reused nonce → direct algebraic recovery (no lattice needed)
│ ├─ Partial nonce leakage → HNP → CVP lattice
│ │ └─ Need enough signatures: n ≥ q_bits / leaked_bits
│ └─ Nonce bias → statistical HNP → larger lattice
│
├─ Knapsack / subset sum?
│ ├─ Low density (d < 0.9408) → CJLOSS lattice attack
│ ├─ High density → lattice attack unlikely to work
│ └─ Super-increasing → greedy algorithm (no lattice needed)
│
├─ LCG / PRNG?
│ ├─ Full outputs known → algebraic recovery (no lattice)
│ ├─ Truncated outputs → CVP on recurrence lattice
│ └─ Unknown modulus → use GCD of output differences
│
├─ NTRU?
│ └─ Build circulant lattice → LLL/BKZ for short key vector
│
└─ Custom problem?
├─ Express as "find small root of polynomial mod N" → Coppersmith
├─ Express as "find lattice point close to target" → CVP
├─ Express as "find short vector in lattice" → SVP / LLL
└─ If none fit → probably not a lattice problem需要使用格方法——选择哪种构造?
│
├─ 与RSA相关?
│ ├─ 消息存在小的未知部分 → 单变量Coppersmith
│ │ └─ 检查:unknown_bits < n_bits / e
│ ├─ 部分因子信息已知 → 模p的Coppersmith
│ │ └─ 使用beta=0.5,X=2^未知比特数
│ ├─ 私钥指数d很小 → Boneh-Durfee
│ │ └─ 检查:d < N^0.292
│ └─ 多个相关等式 → 多变量Coppersmith
│
├─ 与DSA/ECDSA相关?
│ ├─ 随机数重用 → 直接代数恢复(无需格)
│ ├─ 部分随机数泄露 → HNP → CVP格
│ │ └─ 需要足够签名:n ≥ q比特数 / 泄露比特数
│ └─ 随机数偏差 → 统计HNP → 更大的格
│
├─ 背包/子集和问题?
│ ├─ 低密度(d < 0.9408) → CJLOSS格攻击
│ ├─ 高密度 → 格攻击大概率无效
│ └─ 超递增序列 → 贪心算法(无需格)
│
├─ LCG/PRNG问题?
│ ├─ 完整输出已知 → 代数恢复(无需格)
│ ├─ 截断输出 → 递推格上的CVP
│ └─ 模数未知 → 对输出差值求GCD
│
├─ NTRU问题?
│ └─ 构建循环格 → LLL/BKZ寻找短密钥向量
│
└─ 自定义问题?
├─ 可表示为「寻找多项式模N的小根」 → Coppersmith
├─ 可表示为「寻找接近目标的格点」 → CVP
├─ 可表示为「寻找格中的短向量」 → SVP / LLL
└─ 都不满足 → 大概率不是格相关问题10. COMMON PITFALLS
10. 常见陷阱
| Pitfall | Symptom | Fix |
|---|---|---|
| Root bound too large | | Reduce X, increase epsilon, verify bound satisfies Coppersmith criterion |
| Wrong scaling | LLL finds irrelevant short vector | Scale columns so target vector has balanced entries |
| Insufficient dimension | Solution not in reduced basis | Increase m parameter (more shift polynomials) |
| Wrong beta | Coppersmith doesn't find factor | beta=0.5 for half-size factor, beta=1.0 for full modulus |
| Too few signatures (HNP) | Lattice attack fails | Collect more signatures with nonce bias |
| BKZ block size too small | Solution not short enough | Increase block size (try 25, 30, 40) |
| Integer overflow | SageMath crashes | Use ZZ ring explicitly, avoid mixing QQ and ZZ |
| 陷阱 | 表现 | 修复方案 |
|---|---|---|
| 根边界过大 | | 减小X,增大epsilon,验证边界满足Coppersmith条件 |
| 缩放错误 | LLL返回无关的短向量 | 缩放列向量,使目标向量的元素大小均衡 |
| 维度不足 | 规约基中不存在解 | 增大m参数(添加更多平移多项式) |
| beta参数错误 | Coppersmith找不到因子 | 半长因子用beta=0.5,全模数用beta=1.0 |
| 签名数量不足(HNP) | 格攻击失败 | 收集更多存在随机数偏差的签名 |
| BKZ块大小过小 | 解的长度不够短 | 增大块大小(尝试25、30、40) |
| 整数溢出 | SageMath崩溃 | 显式使用ZZ环,避免混合QQ和ZZ类型 |