CTF-Crypto培训笔记-现代密码

一、DES加密算法

DES全称Data Encryption Standard(数据加密标准),它奠定了现代分组密码设计的基础。DES是一个分组密码,分组长度64位,密钥有效长度56位,使用16轮迭代的Feistel网络结构。

1 整体结构:Feistel网络的经典实现

1.1 Feistel网络的核心思想

Feistel网络将数据块分为左右两半(各32位): L i L_i Li 和 $ R_i$ 。每一轮加密只对右半部分应用轮函数 F F F,然后与左半部分异或,最后交换左右。其数学描述为:
L i + 1 = R i R i + 1 = L i ⊕ F ( R i , K i ) \begin{array}{l}{{L_{i+1}=R_{i}}}\\ {{R_{i+1}=L_{i}\oplus F(R_{i},K_{i})}}\end{array} Li+1=RiRi+1=LiF(Ri,Ki)这种结构的巨大优势在于加解密完全相同(只需逆序使用子密钥),极大简化了硬件实现。
DES的16轮Feistel结构如下:

  1. 初始置换(IP):对64位明文进行固定比特重排。
  2. 16轮迭代:每轮使用不同的48位子密钥 K i K_i Ki
  3. 左右交换:第16轮输出后,交换左右两半。
  4. 逆初始置换(IP⁻¹):得到64位密文。

2 轮函数F的细节

轮函数 F ( R , K ) F(R,K) F(R,K) 是DES安全性的核心,它将32位右半部分 R R R 和48位子密钥 K K K 映射为32位输出。步骤如下:

2.1 扩展置换(E)

将32位 R R R 扩展为48位。这个置换不仅复制了16个Byte(其中一些Byte出现在两个位置上),还让输出Byte与输入Byte产生依赖关系,便于后续S-box压缩后仍能影响多个比特。

2.2 与子密钥异或

扩展后的48位与当前轮的48位子密钥 K i K_i Ki 进行XOR。

2.3 S-box压缩

48位结果分成8个6位块,每块送入一个S-box(S₁ 到 S₈)。每个S-box将6位输入映射为4位输出。S-box是非线性的——它是DES唯一的非线性组件,提供了密码强度。
每个S-box是一个 4 × 16 4×16 4×16 的查找表。6位输入:首位和末位组成行号(0-3),中间4位组成列号(0-15),输出对应单元格的4位值。
例如,S₁的查找表(十六进制):

行0: 0xE,0x4,0xD,0x1,0x2,0xF,0xB,0x8,0x3,0xA,0x6,0xC,0x5,0x9,0x0,0x7
行1: 0x0,0xF,0x7,0x4,0xE,0x2,0xD,0x1,0xA,0x6,0xC,0xB,0x9,0x5,0x3,0x8
行2: 0x4,0x1,0xE,0x8,0xD,0x6,0x2,0xB,0xF,0xC,0x9,0x7,0x3,0xA,0x5,0x0
行3: 0xF,0xC,0x8,0x2,0x4,0x9,0x1,0x7,0x5,0xB,0x3,0xE,0xA,0x0,0x6,0xD

2.4 P置换(P)

8个S-box输出的32位比特经过一个固定的P置换,将比特打乱,确保每个S-box的输出在下一轮扩散到多个S-box的输入。

3 密钥调度

DES从56位有效密钥生成16个48位子密钥。过程如下:

  1. 初始64位密钥(含8位奇偶校验)经过置换选择PC-1,去掉校验位并重排,得到56位 C 0 C_0 C0 D 0 D_0 D0(各28位)。
  2. i = 1 i=1 i=1 16 16 16
    • C i − 1 C_{i-1} Ci1 D i − 1 D_{i-1} Di1 循环左移1或2位(轮次1,2,9,16左移1位,其他左移2位)。
    • 将移位后的 C i C_i Ci D i D_i Di 合并,经过置换选择PC-2(选择48位)得到子密钥 K i K_i Ki

PC-1和PC-2的置换表在标准中固定。

二、AES加密算法

AES全称Advanced Encryption Standard(高级加密标准),它是目前全球使用最广泛的对称加密算法,其设计融合了代换-置换网络(SPN)结构与有限域代数。

1 AES的代数结构

1.1 有限域 G F ( 2 8 ) GF(2^8) GF(28)

AES的所有操作都定义在有限域 G F ( 2 8 ) GF(2^8) GF(28) 上,具体采用不可约多项式:
m ( x ) = x 8 + x 4 + x 3 + x + 1 m(x) = x^8 + x^4 + x^3 + x + 1 m(x)=x8+x4+x3+x+1
每个字节可以视为一个系数在 { 0 , 1 } \{0, 1\} {0,1} 上的多项式,例如字节0x57=01010111对应多项
x 6 + x 4 + x 3 + x + 1 x^6 + x^4 + x^3 + x + 1 x6+x4+x3+x+1
加法和乘法都是模 m ( x ) m(x) m(x) 下的域运算:

  • 加法:按位 X O R XOR XOR(相同多项式次数系数相加模2)。
  • 乘法:多项式乘法后模 m ( x ) m(x) m(x)

1.1 状态矩阵

AES处理固定128位(16字节)的数据块,将其组织为 4 × 4 4×4 4×4 字节矩阵(列优先):
S t a t e = [ s 0 , 0 s 0 , 1 s 0 , 2 s 0 , 3 s 1 , 0 s 1 , 1 s 1 , 2 s 1 , 3 s 2 , 0 s 2 , 1 s 2 , 2 s 2 , 3 s 3 , 0 s 3 , 1 s 3 , 2 s 3 , 3 ] \mathrm { S t a t e } = \left[ \begin{array} { l l l l } { s _ { 0 , 0 } } & { s _ { 0 , 1 } } & { s _ { 0 , 2 } } & { s _ { 0 , 3 } } \\ { s _ { 1 , 0 } } & { s _ { 1 , 1 } } & { s _ { 1 , 2 } } & { s _ { 1 , 3 } } \\ { s _ { 2 , 0 } } & { s _ { 2 , 1 } } & { s _ { 2 , 2 } } & { s _ { 2 , 3 } } \\ { s _ { 3 , 0 } } & { s _ { 3 , 1 } } & { s _ { 3 , 2 } } & { s _ { 3 , 3 } } \end{array} \right] State= s0,0s1,0s2,0s3,0s0,1s1,1s2,1s3,1s0,2s1,2s2,2s3,2s0,3s1,3s2,3s3,3
输入明文按字节填充:前4字节为第一列,次4字节为第二列,以此类推。

2 AES的轮函数结构

AES是一个迭代分组密码,轮数 N r N_r Nr 取决于密钥长度:

  • AES-128: N r = 10 N_r=10 Nr=10,密钥长度128位
  • AES-192: N r = 12 N_r=12 Nr=12,密钥长度192位
  • AES-256: N r = 14 N_r=14 Nr=14,密钥长度256位

每一轮(除最后一轮外)包含四个可逆变换:

密钥长度分组长度迭代轮数
128bit128bit10 轮
192bit128bit12 轮
256bit128bit14 轮

不同轮数的AES密钥逻辑框架完全一致,仅循环轮数不同。

2.1 SubBytes(字节代换)

独立对状态矩阵的每个字节应用S-box(代换盒)。S-box是一个 16 × 16 16×16 16×16 的查找表,其构造具有强代数性质:

  • 计算字节在 G F ( 2 8 ) GF(2^8) GF(28) 上的乘法逆元(0x00 映射到自身)。
  • 对逆元应用仿射变换: b i ′ = b i ⊕ b ( i + 4 )   m o d   8 ⊕ b ( i + 5 )   m o d   8 ⊕ b ( i + 6 )   m o d   8 ⊕ b ( i + 7 )   m o d   8 ⊕ c i b'_i = b_i \oplus b_{(i+4) \bmod 8} \oplus b_{(i+5) \bmod 8} \oplus b_{(i+6) \bmod 8} \oplus b_{(i+7) \bmod 8} \oplus c_i bi=bib(i+4)mod8b(i+5)mod8b(i+6)mod8b(i+7)mod8ci其中 c i c_i ci 是常数0x63的第 i i i 位。

2.2 ShiftRows(行移位)

将状态矩阵的每一行循环左移不同字节数:

  • 第0行:不移位
  • 第1行:左移1字节
  • 第2行:左移2字节
  • 第3行:左移3字节

作用是将列的扩散到其他列。

2.3 MixColumns(列混合)

对每一列独立进行线性变换。将列视为 G F ( 2 8 ) GF(2^8) GF(28) 上的4次多项式,并乘以固定多项式: c ( x ) = 0 x 03 ⋅ x 3 + 0 x 01 ⋅ x 2 + 0 x 01 ⋅ x + 0 x 02 c(x) = 0\mathrm{x}03 \cdot x^3 + 0\mathrm{x}01 \cdot x^2 + 0\mathrm{x}01 \cdot x + 0\mathrm{x}02 c(x)=0x03x3+0x01x2+0x01x+0x02 x 4 + 1 x^4+1 x4+1 。矩阵表示如下:
[ s 0 , j ′ s 1 , j ′ s 2 , j ′ s 3 , j ′ ] = [ 02 03 01 01 01 02 03 01 01 01 02 03 03 01 01 02 ] ⋅ [ s 0 , j s 1 , j s 2 , j s 3 , j ] \begin{bmatrix}s _ { 0 , j } ^ { \prime } \\ s _ { 1 , j } ^ { \prime } \\ s _ { 2 , j } ^ { \prime } \\ s _ { 3 , j } ^ { \prime } \\ \end{bmatrix}= \begin{bmatrix} 0 2 & 0 3 & 0 1 & 0 1 \\ 0 1 & 0 2 & 0 3 & 0 1 \\ 0 1 & 0 1 & 0 2 & 0 3 \\ 0 3 & 0 1 & 0 1 & 0 2 \end{bmatrix} \cdot \begin{bmatrix} s _ { 0 , j } \\ s _ { 1 , j } \\ s _ { 2 , j } \\ s _ { 3 , j } \end{bmatrix} s0,js1,js2,js3,j = 02010103030201010103020101010302 s0,js1,js2,js3,j
其中乘法与加法均在 G F ( 2 8 ) GF(2^8) GF(28) 中进行。

注意:最后一轮没有MixColumns,以保证加解密结构对称。

2.4 AddRoundKey(轮密钥加)

将状态矩阵与当前轮的轮密钥(128位)逐字节进行 X O R XOR XOR 运算。轮密钥由原始密钥通过密钥扩展算法生成。

3 密钥扩展(Key Schedule)

对于AES-128,原始密钥16字节被扩展为 11 × 128 11×128 11×128 位的轮密钥(第0轮到第10轮)。扩展过程使用(Word,4字节)为单位:

  • 将原始密钥分为4个字: W [ 0 ] , W [ 1 ] , W [ 2 ] , W [ 3 ] W[0],W[1],W[2],W[3] W[0],W[1],W[2],W[3]
  • 对于 i = 4 i=4 i=4 43 43 43
    • i m o d    4 ≠ 0 : W [ i ] = W [ i − 4 ] ⊕ W [ i − 1 ] i \mod 4 \neq 0: W[i] = W[i - 4] \oplus W[i - 1] imod4=0:W[i]=W[i4]W[i1]
    • i m o d    4 = 0 : i \mod 4 = 0: imod4=0:
      • 循环左移 W [ i − 1 ] W[i−1] W[i1] 的4个字节
      • 对每个字节应用S-box(SubWord)
      • 与轮常数 Rcon[i/4] 异或(轮常数是 G F ( 2 8 ) GF(2 ^8) GF(28) x i / 4 − 1 x^{i/4-1} xi/41 的值,如0x01, 0x02, 0x04, 0x08, 0x10, ...
      • 最后与 W [ i − 4 ] W[i−4] W[i4] 异或得到 W [ i ] W[i] W[i]

AES-192和AES-256的扩展类似,但轮常数和更新规则略有不同。

4 加解密流程

4.1加密

 1. 初始 AddRoundKey(State, RoundKey[0])
 2. 对 round = 1 到 N_r - 1:
    SubBytes(State)
    ShiftRows(State)
    MixColumns(State)
    AddRoundKey(State, RoundKey[round])
 3. 最后一轮:
    SubBytes(State)
    ShiftRows(State)
    AddRoundKey(State, RoundKey[N_r])

4.2 解密

所有操作都是逆变换,注意顺序相反:

InvSubBytes(使用逆S-box)
InvShiftRows(循环右移)
InvMixColumns(乘矩阵的逆)
AddRoundKey(因为XOR是对合,所以相同)

5 分组密码工作模式

模式并行性错误传播特点
ECB完全并行块内不安全,相同明文块产生相同密文块
CBC解密并行,加密串行影响两个块需要随机IV,经典但不可并行加密
CTR完全并行将块密码变为流密码,简单高效
GCM完全并行认证加密(AEAD),同时提供机密性和完整性

三、RSA加密算法

1977年,三位麻省理工学院的科学家 Ron Rivest、Adi Shamir 和 Len Adleman 发表了一篇论文《A Method for Obtaining Digital Signatures and Public-Key Cryptosystems》,提出了基于大整数因数分解困难性的公钥加密算法。RSA之名取自他们姓氏的首字母。RSA的核心理念是:加密密钥(公钥)可以公开,解密密钥(私钥)只能由接收方掌握。RSA的安全依赖于一个数学事实:

两个大素数的乘积很容易计算,但反过来分解该乘积极其困难。

1 数学基础

1.1 预备知识

  • 模运算: a ≡ b ( m o d n ) a \equiv b \pmod{n} ab(modn) 表示 n n n 整除 a − b a - b ab
  • 欧拉函数 φ ( n ) \varphi(n) φ(n):小于等于 n n n 且与 n n n 互质的正整数的个数。对两个不同素数 p p p q q q φ ( p q ) = ( p − 1 ) ( q − 1 ) \varphi(pq)=(p-1)(q-1) φ(pq)=(p1)(q1)
  • 欧拉定理: gcd ⁡ ( a , n ) = 1 \gcd(a,n)=1 gcd(a,n)=1, 则 a φ ( n ) ≡ 1 ( m o d n ) a^{\varphi(n)}\equiv 1 \pmod{n} aφ(n)1(modn)

1.2 密钥生成

  1. 随机选择两个大素数 p p p q q q (例如512位以上,实际推荐2048位)。
  2. 计算 n = p × q n = p \times q n=p×q n n n 的二进制长度就是密钥长度。
  3. 计算 φ ( n ) = ( p − 1 ) ( q − 1 ) \varphi(n) = (p - 1)(q - 1) φ(n)=(p1)(q1)
  4. 选一个整数 e e e,满足 1 < e < φ ( n ) 1 < e < \varphi(n) 1<e<φ(n) gcd ⁡ ( e , φ ( n ) ) = 1 \gcd(e, \varphi(n)) = 1 gcd(e,φ(n))=1。常用的 e e e 是 65537 ( 2 16 + 1 ) (2^{16}+1) (216+1),因其为素数且二进制表示只有两个1,加密运算速度快。
  5. 计算 e e e φ ( n ) \varphi(n) φ(n) 的模逆 d d d,即 e × d ≡ 1 ( m o d φ ( n ) ) e \times d \equiv 1 \pmod{\varphi(n)} e×d1(modφ(n))。可用扩展欧几里得算法求解。

公钥: ( n , e ) (n, e) (n,e)
私钥: ( n , d ) (n, d) (n,d)

1.3 加密与解密

  • 加密:对明文 m m m(视为整数,且 0 ≤ m < n 0 \le m < n 0m<n),计算密文: c = m e   m o d   n c = m^e \bmod n c=memodn
  • 解密:对密文 c c c,计算: m = c d   m o d   n m = c^d \bmod n m=cdmodn

为什么解密能恢复明文?因为:
c d ≡ ( m e ) d = m e d ≡ m k φ ( n ) + 1 ≡ m ⋅ ( m φ ( n ) ) k ≡ m ⋅ 1 k = m ( m o d n ) c^d \equiv (m^e)^d = m^{ed} \equiv m^{k\varphi(n)+1} \equiv m \cdot (m^{\varphi(n)})^k \equiv m \cdot 1^k = m \pmod n cd(me)d=medmkφ(n)+1m(mφ(n))km1k=m(modn)中间用到了欧拉定理(当 gcd ⁡ ( m , n ) = 1 \gcd(m,n) = 1 gcd(m,n)=1 时)。对于 m m m n n n 不互质的极罕见情况,由 p p p q q q 为素数也可证明成立。

1.4 数值示例

  1. p = 61 p=61 p=61, q = 53 q=53 q=53
    n = 61 × 53 = 3233 n=61 \times 53=3233 n=61×53=3233
    φ ( n ) = ( p − 1 ) × ( q − 1 ) = 60 × 52 = 3120 \varphi(n)=(p-1) \times (q-1) = 60 \times 52=3120 φ(n)=(p1)×(q1)=60×52=3120
  2. e = 17 e=17 e=17 (与3120互质)
    计算 d = e − 1   m o d   φ ( n ) = 17 − 1   m o d   3120 = 2753 d=e^{-1} \bmod \varphi(n)=17^{-1}\bmod3120=2753 d=e1modφ(n)=171mod3120=2753
    (因为 17 × 2753 = 46801 = 15 × 3120 + 1 17 \times 2753=46801=15 \times 3120+1 17×2753=46801=15×3120+1 )
  3. 公钥 ( n , e ) = ( 3233 , 17 ) (n,e)=(3233,17) (n,e)=(3233,17)
    私钥 ( n , d ) = ( 3233 , 2753 ) (n,d)=(3233,2753) (n,d)=(3233,2753)
  4. 加密明文 m = 65 m=65 m=65: c = m e   m o d   n = 65 17   m o d   3233 = 2790 c=m^e\bmod n=65^{17} \bmod 3233=2790 c=memodn=6517mod3233=2790
  5. 解密: c   m o d   n = 2790 2753   m o d   3233 = 65 c \bmod n = 2790^{2753} \bmod 3233=65 cmodn=27902753mod3233=65

1.5 中国剩余定理 (CRT) 加速

解密时,私钥持有者知道 p p p q q q,可以分别计算 c d   m o d   p c^d \bmod p cdmodp c d   m o d   q c^d \bmod q cdmodq,再用 CRT 组合结果。这样速度提升约4倍。存储私钥时通常包含

p , q p, q p,q,
d P = d   m o d   ( p − 1 ) dP = d \bmod (p - 1) dP=dmod(p1),
d Q = d   m o d   ( q − 1 ) dQ = d \bmod (q - 1) dQ=dmod(q1),
q I n v = q − 1   m o d   p qInv = q^{-1} \bmod p qInv=q1modp

攻击方式

1 破解模数n(已知 n, e, c,分解 n 求 p, q)

按照上述数值示例解题即可

import gmpy2
from Crypto.Util.number import long_to_bytes

n_hex = "0x..."; 
e_hex = "0x10001"; #65537
c_hex = "0x..."
n = int(n_hex, 16); 
e = int(e_hex, 16); 
c = int(c_hex, 16)

# 方式1: 使用 factordb 或 sympy(需安装)
from sympy import factorint
factors = factorint(n)
p, q = sorted(factors.keys())  # p, q 为素数

# 方式2: 手动试除(仅当 n 很小)
# for i in range(2, 100000):
#     if n % i == 0:
#         p, q = i, n // i
#         break

phi = (p-1)*(q-1)
d = gmpy2.invert(e, phi)
m = pow(c, d, n)
print(long_to_bytes(m))

2 共模攻击(相同 n,不同 e1, e2)

已知e1,e2,c1,c2,n,求解m(不需要知道对应的d1,d2)

原理:
同一明文 m m m,用两个互质的公钥指数 e 1 , e 2 e_1, e_2 e1,e2 加密得 c 1 , c 2 c_1, c_2 c1,c2。若 g c d ( e 1 , e 2 ) = 1 gcd(e_1, e_2)=1 gcd(e1,e2)=1,则可利用扩展欧几里得算法找到 x , y x, y x,y 使得 e 1 x + e 2 y = 1 e_1x + e_2y = 1 e1x+e2y=1,进而:
m = ( c 1 x × c 2 y )   m o d   n m = (c_1^x \times c_2^y) \bmod n m=(c1x×c2y)modn(注意 x , y x, y x,y 可能为负,用模逆处理)。

适用条件: e 1 , e 2 e_1, e_2 e1,e2 互质,且 n n n 相同。

步骤:

  1. 计算 gcd(e1, e2) 应为 1。
  2. 扩展欧几里得求 s, t 使 e1s + e2t = 1。
  3. 若 s < 0,则 c1 = gmpy2.invert(c1, n),取 s = -s;同理处理 t。
  4. m = pow(c1, s, n) * pow(c2, t, n) % n。
import gmpy2

n_hex = "0x...";
e1_hex = "0x...";
e2_hex = "0x..."
c1_hex = "0x...";
c2_hex = "0x..."
n = int(n_hex, 16);
e1 = int(e1_hex, 16);
e2 = int(e2_hex, 16)
c1 = int(c1_hex, 16);
c2 = int(c2_hex, 16)

g, s, t = gmpy2.gcdext(e1, e2)  # g = e1*s + e2*t
assert g == 1

if s < 0:
    c1 = gmpy2.invert(c1, n)
    s = -s
if t < 0:
    c2 = gmpy2.invert(c2, n)
    t = -t

m = pow(c1, s, n) * pow(c2, t, n) % n
print(long_to_bytes(m))

3 模不互素(多个 n 共享素数)

原理:
若两个模数 n 1 , n 2 n_1, n_2 n1,n2 有公共素数因子(即 g c d ( n 1 , n 2 ) > 1 gcd(n_1, n_2) > 1 gcd(n1,n2)>1),则可分解它们。通常用于给定多个 n n n 中某两个不互素。

适用条件:至少两个 n n n,计算 g = g c d ( n 1 , n 2 ) g = gcd(n_1, n_2) g=gcd(n1,n2),若 1 < g < n 1 1 < g < n_1 1<g<n1,则 g g g 为素数因子。

步骤:

  1. 对每一对 ( n i , n j ) (n_i, n_j) (ni,nj) 计算 g c d gcd gcd,找到公共因子 p p p
  2. q i = n i / / p q_i = n_i // p qi=ni//p q j = n j / / p q_j = n_j // p qj=nj//p
  3. 解密对应的密文(需知道对应 e e e c c c)。
from math import gcd

n1_hex = "0x...";
n2_hex = "0x..."
n1 = int(n1_hex, 16);
n2 = int(n2_hex, 16)

p = gcd(n1, n2)
assert p > 1 and p < n1
q1 = n1 // p
q2 = n2 // p
print(f"p = {p}, q1 = {q1}, q2 = {q2}")

4 e = 2, 4, 8 …(低加密指数,但 e 为偶数时的 Rabin 密码)

适用条件: e = 2 k e = 2^k e=2k,且 n n n 为两个素数乘积。

步骤(以 e = 2 e=2 e=2为例):

c c c n n n 的平方根,即解 x 2 ≡ c   m o d   n x^2 ≡ c \bmod n x2cmodn
利用 p , q p,q pq 分别求平方根后 C R T CRT CRT 组合得到四个根。
选择可读的那一个。

import gmpy2

c = int(c_hex, 16)
# 假设已分解得到 p, q
p, q = ...
n = p * q

# 模 p 平方根
def sqrt_mod(a, p):
    return gmpy2.powmod(a, (p+1)//4, p)  # p ≡ 3 mod 4 时成立

# 若 p ≡ 3 mod 4
rp = sqrt_mod(c, p)
rq = sqrt_mod(c, q)

# 中国剩余定理组合四个根
from Crypto.Util.number import long_to_bytes
for sign_p in (rp, p - rp):
    for sign_q in (rq, q - rq):
        m = gmpy2.crt([sign_p, sign_q], [p, q])[0]
        # 尝试转为字符串
        try:
            print(long_to_bytes(m))
        except:
            pass

p ≡ 1   m o d   4 p ≡ 1 \bmod 4 p1mod4,需用 Tonelli-Shanks 算法求平方根(使用 gmpy2.sqrtmodsympy.ntheory.sqrt_mod)。

5 e = 3, 5, 7 …(低加密指数小明文攻击)

原理:
m e < n m^e < n me<n,则 c = m e c = m^e c=me 直接开 e e e 次方即可得 m m m。即使 m e m^e me 略大于 n n n,也可通过添加 k × n k \times n k×n 并开方爆破 k k k(Coppersmith 攻击)。

适用条件:e 很小(3,5,7 常见),且 m 足够小(或知道部分明文格式)。

步骤:

计算 m = gmpy2.iroot(c, e),若能开整数根则直接得到。
否则,枚举 k = 0,1,2,... 计算 (c + k*n) 的 e 次根,直到得到整数。
import gmpy2

e = 3
c = int(c_hex, 16)
n = int(n_hex, 16)

for k in range(100000):
    m, exact = gmpy2.iroot(c + k * n, e)
    if exact:
        print(long_to_bytes(m))
        break

6 d泄漏攻击(已知 d, n, e, c)

一般是已知私钥d的16进制字符串,需要处理

n_hex = "0x...";
d_hex = "0x...";
c_hex = "0x..."
n = int(n_hex, 16);
d = int(d_hex, 16); 
c = int(c_hex, 16)
m = pow(c, d, n)
print(long_to_bytes(m))

7 dp和dq泄漏(已知 p, q, dp, dq, c,求解 mp,mq,InvQ,m)

原理:

d p = d   m o d   ( p − 1 ) dp = d \bmod (p-1) dp=dmod(p1)
d q = d   m o d   ( q − 1 ) dq = d \bmod (q-1) dq=dmod(q1)

利用它们可以避免直接求 d,而通过 CRT 计算 m   m o d   p m \bmod p mmodp m   m o d   q m \bmod q mmodq 再组合。
步骤:

1. 计算 mp = pow(c, dp, p),mq = pow(c, dq, q)。
2. 计算 q_inv = gmpy2.invert(q, p)(或 p_inv)。
3. 利用 CRT:m = mp + p * ((mq - mp) * q_inv % q)。
import gmpy2
from Crypto.Util.number import long_to_bytes

p_hex = "0x...";
q_hex = "0x..."
dp_hex = "0x...";
dq_hex = "0x...";
c_hex = "0x..."
p = int(p_hex, 16);
q = int(q_hex, 16)
dp = int(dp_hex, 16);
dq = int(dq_hex, 16)
c = int(c_hex, 16)

mp = pow(c, dp, p)
mq = pow(c, dq, q)

q_inv = gmpy2.invert(q, p)  # 实际上标准 CRT 用 m = mp + p * ((mq - mp) * q_inv % q)
# 更稳健的公式:
m = (mp + p * ((mq - mp) * gmpy2.invert(p, q) % q)) % (p * q)
# 或者使用 gmpy2.crt
# m = gmpy2.crt([mp, mq], [p, q])[0]
print(long_to_bytes(m))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值