解的是HNP(Hidden Number Problem),DLP和格扯上关系了.
题目:https://paste.ubuntu.com/p/F38PPcczqj/
题目是一个Diffie Hellman的KE:
A ≡ g a ( m o d p ) B ≡ g B ( m o d p ) s ≡ A b ≡ g a b ( m o d p ) A \equiv g^a \pmod p \\
B \equiv g^B \pmod p \\
s \equiv A^b \equiv g^{ab} \pmod p
A ≡ g a ( mod p ) B ≡ g B ( mod p ) s ≡ A b ≡ g ab ( mod p )
知道A 、 B 、 g 、 p A、B、g、p A 、 B 、 g 、 p ,求s s s ;给了一个Oracle(即to_bob),可以实现:
O ( m ) = ( m b ( m o d p ) ) − k m k m = ( m b ( m o d p ) ) & ( 2 64 − 1 ) O(m) = (m^b \pmod p) - k_m\\
k_m=(m^b \pmod p)\ \&\ (2^{64}-1)
O ( m ) = ( m b ( mod p )) − k m k m = ( m b ( mod p )) & ( 2 64 − 1 )
即返回低64 64 64 位被mask为0 0 0 的m b ( m o d p ) m^b \pmod p m b ( mod p ) ,在k m k_m k m 比m b ( m o d p ) m^b \pmod p m b ( mod p ) 小的情况下可以写成:
O ( m ) = m b − k m ( m o d p ) O(m) = m^b - k_m \pmod p
O ( m ) = m b − k m ( mod p )
这题的解法可以直接照搬[MH20],但远一点可以追溯到[BV96];首先进行两次Oracle的查询:
c h o o s e c → C ≡ g c ( m o d p ) r 1 ≡ O ( A ) ≡ A b − k 1 ≡ s − k 1 ( m o d p ) r 2 ≡ O ( A C ) ≡ ( A C ) b − k 2 ≡ s B c − k 2 ( m o d p ) choose\ c\ →\ C \equiv g^c \pmod p \\
r_1 \equiv O(A) \equiv A^b - k_1 \equiv s - k_1 \pmod p \\
r_2 \equiv O(AC) \equiv (AC)^b - k_2 \equiv sB^c - k_2 \pmod p
c h oose c → C ≡ g c ( mod p ) r 1 ≡ O ( A ) ≡ A b − k 1 ≡ s − k 1 ( mod p ) r 2 ≡ O ( A C ) ≡ ( A C ) b − k 2 ≡ s B c − k 2 ( mod p )
记t ≡ B c ( m o d p ) t\equiv B^c \pmod p t ≡ B c ( mod p ) ,记可简化写为:
s ≡ r 1 + k 1 ( m o d p ) s t ≡ r 2 + k 2 ( m o d p ) s \equiv r_1 + k_1 \pmod p \\
st \equiv r_2 + k_2 \pmod p
s ≡ r 1 + k 1 ( mod p ) s t ≡ r 2 + k 2 ( mod p )
联立两式:
r 2 t − 1 + k 2 t − 1 − r 1 − k 1 ≡ s − s ≡ 0 ( m o d p ) r_2t^{-1} + k_2t^{-1} - r_1 - k_1 \equiv s-s \equiv 0 \pmod p
r 2 t − 1 + k 2 t − 1 − r 1 − k 1 ≡ s − s ≡ 0 ( mod p )
展开p p p (记系数k 3 k_3 k 3 )再整理一下:
k 2 t − 1 + ( r 2 t − 1 − r 1 ) + k 3 p = k 1 k_2t^{-1} + (r_2t^{-1}-r_1) + k_3p = k_1
k 2 t − 1 + ( r 2 t − 1 − r 1 ) + k 3 p = k 1
即可构造:
( k 3 , k 2 , 1 ) [ p 0 0 t − 1 1 0 ( r 2 t − 1 − r 1 ) 0 K ] = ( k 1 , k 2 , K ) K ≈ 2 64 (k_3, k_2, 1)
\begin{bmatrix} p & 0 & 0 \\ t^{-1} & 1 & 0 \\ (r_2t^{-1}-r_1) & 0 & K \end{bmatrix}
= (k_1, k_2, K) \\
K \approx 2^{64}
( k 3 , k 2 , 1 ) ⎣ ⎡ p t − 1 ( r 2 t − 1 − r 1 ) 0 1 0 0 0 K ⎦ ⎤ = ( k 1 , k 2 , K ) K ≈ 2 64
记上式为v M = w vM=w v M = w 的话,可以计算(题目的p p p 大概2 256 2^{256} 2 256 ):
σ ( M ) ≈ 3 ∗ 2 320 / 3 ≈ 3 ∗ 2 106 ∥ w ∥ ≈ 3 ∗ 2 64 ∥ w ∥ < σ ( M ) \sigma(M) \approx \sqrt{3} * 2^{320/3} \approx \sqrt{3} * 2^{106} \\
\|w\| \approx \sqrt{3} * 2^{64} \\
\|w\| < \sigma(M)
σ ( M ) ≈ 3 ∗ 2 320/3 ≈ 3 ∗ 2 106 ∥ w ∥ ≈ 3 ∗ 2 64 ∥ w ∥ < σ ( M )
于是上个LLL求最短向量就解出k 1 k_1 k 1 ,进而解出s s s ;先给个本地测试的脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 bits = 64 p = 62606792596600834911820789765744078048692259104005438531455193685836606544743 fp = [2 , 139 , 42798235205263 , 181440306484546562787712787 , 29001270706552925994696287850627469 ] F.<a> = GF(p) g = F(5 ) a = randint(1 , p - 1 ) A = pow (g, a) b = randint(1 , p - 1 ) B = pow (g, b) s = pow (A, b) print ('a = %s' % a)print ('b = %s' % b)print ('A = %s' % A)print ('B = %s' % B)print ('s = %s' % s)def leak (msg ): tmp_s = pow (msg, b) leak = tmp_s >> bits leak = leak << bits return leak c = randint(1 , p - 1 ) C = pow (g, c) t = pow (B, c) ti = t^(-1 ) r1 = leak(A) r2 = leak(A*C) K = 2 ^64 M = matrix(ZZ, [ [p , 0 , 0 ], [ti , 1 , 0 ], [r2*ti-r1, 0 , K] ]) L = M.LLL() print ('' )print (K)got = int (r1)+L[0 ][0 ] print (got, got==s)
然后改一下就是打远端的Exp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 from pwn import *bits = 64 p = 62606792596600834911820789765744078048692259104005438531455193685836606544743 F = GF(p) g = F(5 ) r = remote('39.105.38.192' , 30000 ) r.recvuntil(b'$' ) r.sendline(b'1' ) A = F(int (r.recvline())) print ('A = %d' % A)r.recvuntil(b'$' ) r.sendline(b'2' ) B = F(int (r.recvline())) print ('B = %d' % B)c = randint(1 , p - 1 ) C = pow (g, c, p) t = pow (B, c, p) ti = t^(-1 ) r.recvuntil(b'$' ) r.sendline(b'3' ) r.recvuntil(b'To Bob: ' ) r.sendline(bytes (str (A), encoding='ascii' )) r1 = int (r.recvline()) print ('r1 = %d' % r1)r.recvuntil(b'$' ) r.sendline(b'3' ) r.recvuntil(b'To Bob: ' ) r.sendline(bytes (str (A*C), encoding='ascii' )) r2 = int (r.recvline()) print ('r2 = %d' % r2)K = 2 ^64 M = matrix(ZZ, [ [p , 0 , 0 ], [ti , 1 , 0 ], [r2*ti-r1, 0 , K] ]) L = M.LLL() got = int (r1)+L[0 ][0 ] print (L[0 ][2 ] == K)print ('got -> %d' % got)r.recvuntil(b'$' ) r.sendline(b'4' ) r.recvuntil(b'secret: ' ) r.sendline(bytes (str (got), encoding='ascii' )) print (r.recv())r.close()
其实[MH20]中还介绍了很多类似的攻击(即泄露partial information),可以mark一下。
[MH20] De Micheli G, Heninger N. Recovering cryptographic keys from partial information, by example[J]. 2020.
[BV96] Boneh D, Venkatesan R. Hardness of computing the most significant bits of secret keys in Diffie-Hellman and related schemes[C]//Annual International Cryptology Conference. Springer, Berlin, Heidelberg, 1996: 129-142.