虽然只做了两道格的。
MyErrorLearn·
题目:MyErrorLearn.py (代码的main.py
)
题目代码不长,大概意思是,可以访问两次 X妮Oracle (三次留一次提交secret
所以是两次),每次返回d
和r
,其中d ≡ ( s + r ) − 1 − r ′ ( m o d p ) d \equiv (s+r)^{-1} - r' \pmod p d ≡ ( s + r ) − 1 − r ′ ( mod p ) ,p p p 是1024 bits,r ′ r' r ′ 是246 bits,两次访问后可以获得d 1 d_1 d 1 、d 2 d_2 d 2 、r 1 r_1 r 1 、r 2 r_2 r 2 ,目标是求出s s s 。
首先,若知道r 1 ′ r_1' r 1 ′ 或者r 2 ′ r_2' r 2 ′ 就可求出s s s ,可以简单推导一下(虽然下面exp用了另一种更复杂的方法,但是我懒得改了就直接贴了):
d ≡ ( s + r ) − 1 − r ′ ( d + r ′ ) ( s + r ) ≡ 1 ( d + r ′ ) s ≡ 1 − ( d + r ′ ) r s ≡ ( 1 − ( d + r ′ ) r ) ( d + r ′ ) − 1 s ≡ ( d + r ′ ) − 1 − r ( m o d p ) \begin{aligned}
d &\equiv (s+r)^{-1} - r' \\
(d + r') (s + r) &\equiv 1 \\
(d + r') s &\equiv 1 - (d + r') r \\
s &\equiv (1 - (d + r') r) (d + r')^{-1} \\
s &\equiv (d + r')^{-1} - r \pmod p
\end{aligned}
d ( d + r ′ ) ( s + r ) ( d + r ′ ) s s s ≡ ( s + r ) − 1 − r ′ ≡ 1 ≡ 1 − ( d + r ′ ) r ≡ ( 1 − ( d + r ′ ) r ) ( d + r ′ ) − 1 ≡ ( d + r ′ ) − 1 − r ( mod p )
所以可以吧问题转化为求r 1 ′ r_1' r 1 ′ 或者r 2 ′ r_2' r 2 ′ 。而观察可得r 1 ′ r_1' r 1 ′ 、r 2 ′ r_2' r 2 ′ 与p p p 相比都是“小”的,所以自然会想到用格的方法(这个可能需要经验),而格的方法中由于Coppersmith的式子推导比较简单、可以直接调现成的代码 、而且一般(或许是指单条式子?)情况下比普通格的方法效果更好,所以可以先考虑Coppersmith。
下面作简单的式子推导。首先已知的关系是
d 1 ≡ ( s + r 1 ) − 1 − r 1 ′ ( m o d p ) d 2 ≡ ( s + r 2 ) − 1 − r 2 ′ ( m o d p ) d_1 \equiv (s+r_1)^{-1} - r_1' \pmod p \\
d_2 \equiv (s+r_2)^{-1} - r_2' \pmod p
d 1 ≡ ( s + r 1 ) − 1 − r 1 ′ ( mod p ) d 2 ≡ ( s + r 2 ) − 1 − r 2 ′ ( mod p )
如果单用一条式子会遇到一个问题,就s s s 是“大”的、不能被Coppersmith解出的未知数,所以要想方法消去,消去的方法也不难,就是联立两个方程:
( d 1 + r 1 ′ ) ( s + r 1 ) ≡ ( d 2 + r 2 ′ ) ( s + r 2 ) ( d 1 + r 1 ′ ) s + ( d 1 + r 1 ′ ) r 1 ≡ ( d 2 + r 2 ′ ) s + ( d 2 + r 2 ′ ) r 2 ( d 1 + r 2 − d 2 − r 2 ) s ≡ ( d 2 + r 2 ′ ) r 2 − ( d 1 + r 1 ′ ) r 1 ( m o d p ) \begin{aligned}
(d_1 + r_1') (s + r_1) &\equiv (d_2 + r_2') (s + r_2) \\
(d_1 + r_1') s + (d_1 + r_1') r_1 &\equiv (d_2 + r_2') s + (d_2 + r_2') r_2 \\
(d_1 + r_2 - d_2 - r_2) s &\equiv (d_2 + r_2') r_2 - (d_1 + r_1') r_1 \pmod p
\end{aligned}
( d 1 + r 1 ′ ) ( s + r 1 ) ( d 1 + r 1 ′ ) s + ( d 1 + r 1 ′ ) r 1 ( d 1 + r 2 − d 2 − r 2 ) s ≡ ( d 2 + r 2 ′ ) ( s + r 2 ) ≡ ( d 2 + r 2 ′ ) s + ( d 2 + r 2 ′ ) r 2 ≡ ( d 2 + r 2 ′ ) r 2 − ( d 1 + r 1 ′ ) r 1 ( mod p )
由于题目的p p p 并不是取素数,所以为了避免求逆的问题会绕一点弯(虽然其实多试几次也可以避免,不过还是尽量完美一点),为了方便,姑且设(注意都没含s s s ):
s 1 ≡ ( d 2 + r 2 ′ ) r 2 − ( d 1 + r 1 ′ ) r 1 ( m o d p ) s 2 ≡ ( d 1 + r 2 − d 2 − r 2 ) ( m o d p ) \begin{aligned}
s_1 &\equiv (d_2 + r_2') r_2 - (d_1 + r_1') r_1 \pmod p \\
s_2 &\equiv (d_1 + r_2 - d_2 - r_2) \pmod p
\end{aligned}
s 1 s 2 ≡ ( d 2 + r 2 ′ ) r 2 − ( d 1 + r 1 ′ ) r 1 ( mod p ) ≡ ( d 1 + r 2 − d 2 − r 2 ) ( mod p )
把s 2 ⋅ s ≡ s 1 ( m o d p ) s_2 · s \equiv s_1 \pmod p s 2 ⋅ s ≡ s 1 ( mod p ) 的关系代回( d 1 + r 1 ′ ) ( s + r 1 ) ≡ 1 ( m o d p ) (d_1 + r_1') (s + r_1) \equiv 1 \pmod p ( d 1 + r 1 ′ ) ( s + r 1 ) ≡ 1 ( mod p ) 以消去s s s :
s 2 ( d 1 + r 1 ′ ) ( s + r 1 ) ≡ s 2 ( d 1 + r 1 ′ ) ( s 1 + s 2 r 1 ) ≡ s 2 ( d 1 + r 1 ′ ) ( s 1 + s 2 r 1 ) − s 2 ≡ 0 ( m o d p ) \begin{aligned}
s_2 (d_1 + r_1') (s + r_1) &\equiv s_2 \\
(d_1 + r_1') (s_1 + s_2r_1) &\equiv s_2 \\
(d_1 + r_1') (s_1 + s_2r_1) - s_2 &\equiv 0 \pmod p
\end{aligned}
s 2 ( d 1 + r 1 ′ ) ( s + r 1 ) ( d 1 + r 1 ′ ) ( s 1 + s 2 r 1 ) ( d 1 + r 1 ′ ) ( s 1 + s 2 r 1 ) − s 2 ≡ s 2 ≡ s 2 ≡ 0 ( mod p )
最后推出来的式子就是Coppersmith需要的式子(见exp),直接调二元(因为未知数是r 1 ′ r_1' r 1 ′ 和r 2 ′ r_2' r 2 ′ 所以要二元)解出r 1 ′ r_1' r 1 ′ 和r 2 ′ r_2' r 2 ′ ,然后代入求出s s s ,代码是用s ≡ s 1 s 2 − 1 ( m o d p ) s \equiv s_1 s_2^{-1} \pmod p s ≡ s 1 s 2 − 1 ( mod p ) 求的s s s ,也可作参考。
PS:exp的交互用的是pwntools (我也不知道一个搞密码的为什么会有这个东西,逃),直接用pip只会安装到Python中,所以需要用Sage调用pip安装,命令:
1 sage -pip install pwntools --user
PPS:exp中remote应该替换为题目给的nc地址,为了方便调试我用ncat开了个本地的服务,命令:
1 ncat -vc 'python ./main.py' -kl 127.0.0.1 9006
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 load('copper.sage' ) from pwn import *rmo = remote('127.0.0.1' , 9006 ) rmo.readuntil(b'> mod = ' ) p = Integer(rmo.readline()) print (p)rmo.sendline(b'1' ) rmo.readuntil(b'> r = ' ) r1 = Integer(rmo.readline()) rmo.readuntil(b'> d = ' ) d1 = Integer(rmo.readline()) print (r1, d1)rmo.sendline(b'1' ) rmo.readuntil(b'> r = ' ) r2 = Integer(rmo.readline()) rmo.readuntil(b'> d = ' ) d2 = Integer(rmo.readline()) print (r2, d2)P.<r1_, r2_> = PolynomialRing(Zmod(p)) s1 = ((d2 + r2_) * r2 - (d1 + r1_) * r1) s2 = (d1 + r1_ - d2 - r2_) bounds = [2 ^246 , 2 ^246 ] f = (d1 + r1_) * (s1 + s2 * r1) - s2 res = small_roots(f, bounds) print (res)r1_, r2_ = res[0 ] s1 = ((d2 + r2_) * r2 - (d1 + r1_) * r1) s2 = (d1 + r1_ - d2 - r2_) s = s1 * Integer(s2).inverse_mod(p) % p print (s)rmo.sendline(b'2' ) rmo.sendline(bytes (str (s), encoding='utf-8' )) rmo.interactive() rmo.close()
PPPS:更多的Coppermith资料可以参考之前的文章
MyErrorLearnTwice·
题目:MyErrorLearnTwice.py (代码的main.py
)
上一题的魔改,把r ′ r' r ′ 换成328 bits,不能直接用Coppersmith解,但是 X妮Oracle 可以访问15次(同样留一次提交flag)。r ′ r' r ′ 虽然变大了,单跟p p p 相比仍然是“小”的,所以也优先考虑格的方法,直觉上这么多次Oracle的访问有点像藏数问题(HNP) ,下面按HNP的方向构造式子。
首先把第一次访问Oracle的输出作为“基准”,姑且先记作d x d_x d x 和r x r_x r x ,根据上一题推导的
( d 1 + r 1 ′ ) ( s 1 + s 2 r 1 ) − s 2 ≡ 0 ( m o d p ) (d_1 + r_1') (s_1 + s_2r_1) - s_2 \equiv 0 \pmod p
( d 1 + r 1 ′ ) ( s 1 + s 2 r 1 ) − s 2 ≡ 0 ( mod p )
可以得到关系(i = 0 , 1 , . . . , n − 1 i = 0, 1, ..., n-1 i = 0 , 1 , ... , n − 1 ):
( d i + r i ′ ) ( ( d x + r x ′ ) r i − ( d i + r i ′ ) r x + ( d i + r i ′ − d x − r x ′ ) r i ) − ( d i + r i ′ − d x − r x ′ ) ≡ 0 ( d i + r i ′ ) ( d x r x + r x ′ r x − d i r i − r i ′ r i + d i r i + r i ′ r i − d x r i − r x ′ r i ) − ( d i + r i ′ − d x − r x ′ ) ≡ 0 ( d i + r i ′ ) ( d x r x + r x ′ r x − d x r i − r x ′ r i ) − ( d i + r i ′ − d x − r x ′ ) ≡ 0 d i d x ( r x − r i ) + d i ( r x − r i ) r x ′ + d x ( r x − r i ) r i ′ + ( r x − r i ) r x ′ r i ′ − d i − r i ′ + d x + r x ′ ≡ 0 ( d i ( r x − r i ) + 1 ) r x ′ + ( d x ( r x − r i ) − 1 ) r i ′ + ( r x − r i ) r x ′ r i ′ + ( d x − d i + d i d x ( r x − r i ) ) ≡ 0 ( m o d p ) \begin{aligned}
(d_i + r_i') ( (d_x + r_x') r_i - (d_i +r_i') r_x + (d_i + r_i' -d_x - r_x') r_i ) - (d_i + r_i' -d_x -r_x') &\equiv 0 \\
(d_i + r_i') (d_x r_x + r_x' r_x - d_i r_i - r_i' r_i + d_i r_i + r_i' r_i - d_x r_i -r_x' r_i) - (d_i + r_i' -d_x -r_x') &\equiv 0 \\
(d_i + r_i') (d_x r_x + r_x' r_x - d_x r_i -r_x' r_i) - (d_i + r_i' -d_x -r_x') &\equiv 0 \\
d_i d_x (r_x - r_i) + d_i (r_x - r_i) r_x' + d_x (r_x - r_i) r_i' + (r_x - r_i) r_x' r_i' - d_i - r_i' + d_x + r_x' &\equiv 0 \\
(d_i(r_x - r_i) + 1) r_x' + (d_x (r_x - r_i) - 1) r_i' + (r_x - r_i) r_x' r_i' + (d_x - d_i + d_i d_x (r_x - r_i)) &\equiv 0 \pmod p
\end{aligned}
( d i + r i ′ ) (( d x + r x ′ ) r i − ( d i + r i ′ ) r x + ( d i + r i ′ − d x − r x ′ ) r i ) − ( d i + r i ′ − d x − r x ′ ) ( d i + r i ′ ) ( d x r x + r x ′ r x − d i r i − r i ′ r i + d i r i + r i ′ r i − d x r i − r x ′ r i ) − ( d i + r i ′ − d x − r x ′ ) ( d i + r i ′ ) ( d x r x + r x ′ r x − d x r i − r x ′ r i ) − ( d i + r i ′ − d x − r x ′ ) d i d x ( r x − r i ) + d i ( r x − r i ) r x ′ + d x ( r x − r i ) r i ′ + ( r x − r i ) r x ′ r i ′ − d i − r i ′ + d x + r x ′ ( d i ( r x − r i ) + 1 ) r x ′ + ( d x ( r x − r i ) − 1 ) r i ′ + ( r x − r i ) r x ′ r i ′ + ( d x − d i + d i d x ( r x − r i )) ≡ 0 ≡ 0 ≡ 0 ≡ 0 ≡ 0 ( mod p )
下面为了简化,姑且先记:
A i ≡ d i ( r x − r i ) + 1 ( m o d p ) B i ≡ d x ( r x − r i ) − 1 ( m o d p ) C i ≡ r x − r i ( m o d p ) D i ≡ d x − d i + d i d x ( r x − r i ) ( m o d p ) \begin{aligned}
A_i &\equiv d_i(r_x - r_i) + 1 \pmod p \\
B_i &\equiv d_x (r_x - r_i) - 1 \pmod p \\
C_i &\equiv r_x - r_i \pmod p \\
D_i &\equiv d_x - d_i + d_i d_x (r_x - r_i) \pmod p
\end{aligned}
A i B i C i D i ≡ d i ( r x − r i ) + 1 ( mod p ) ≡ d x ( r x − r i ) − 1 ( mod p ) ≡ r x − r i ( mod p ) ≡ d x − d i + d i d x ( r x − r i ) ( mod p )
那就是
A i r x ′ + B i r i ′ + C i r x ′ r i ′ + D i ≡ 0 ( m o d p ) A_i r_x' + B_i r_i' + C_i r_x' r_i' + D_i \equiv 0 \pmod p
A i r x ′ + B i r i ′ + C i r x ′ r i ′ + D i ≡ 0 ( mod p )
接下来需要把r i ′ r_i' r i ′ 孤立出来放在等号右边(因为r i ′ r_i' r i ′ 是”小“的),然后展开模数,最终结果是:
B i − 1 A i r x ′ + B i − 1 C i r x ′ r i ′ + B i − 1 D i − k i p = − r i ′ B_i^{-1} A_i r_x' + B_i^{-1} C_i r_x' r_i' + B_i^{-1} D_i - k_i p = -r_i'
B i − 1 A i r x ′ + B i − 1 C i r x ′ r i ′ + B i − 1 D i − k i p = − r i ′
有了这个式子已经可以构造格了,构造结果不唯一,下面画一下我构造的(其中R = 2 328 R=2^{328} R = 2 328 ,起”配平“作用):
L = [ − p R ⋱ − p R B 0 − 1 C 0 R 1 ⋱ ⋱ B n − 1 − 1 C n − 1 R 1 B 0 − 1 A 0 R ⋯ B n − 1 − 1 A n − 1 R R B 0 − 1 D 0 R ⋯ B n − 1 − 1 D n − 1 R R 2 ] ( 2 n + 2 ) ∗ ( 2 n + 2 ) L =
\begin{bmatrix}
\begin{array}{lll|lll|ll}
-p R & & & & & & & & \\
& \ddots & & & & & & & \\
& & -p R & & & & & & \\
\hline
B_0^{-1} C_0 R & & & 1 & & & & & \\
& \ddots & & & \ddots & & & & \\
& & B_{n-1}^{-1} C_{n-1} R & & & 1 & & & \\
\hline
B_0^{-1} A_0 R & \cdots & B_{n-1}^{-1} A_{n-1} R & & & & R & & \\
B_0^{-1} D_0 R & \cdots & B_{n-1}^{-1} D_{n-1} R & & & & & R^2 & \\
\end{array}
\end{bmatrix}_{(2n+2)*(2n+2)}
L = ⎣ ⎡ − pR B 0 − 1 C 0 R B 0 − 1 A 0 R B 0 − 1 D 0 R ⋱ ⋱ ⋯ ⋯ − pR B n − 1 − 1 C n − 1 R B n − 1 − 1 A n − 1 R B n − 1 − 1 D n − 1 R 1 ⋱ 1 R R 2 ⎦ ⎤ ( 2 n + 2 ) ∗ ( 2 n + 2 )
构造出来的关系是:
v ⋅ L = ( k 0 , . . . , k n − 1 , ∣ r x ′ r 0 ′ , . . . , r x ′ r n − 1 ′ , ∣ r x ′ , 1 ) ⋅ L = ( − r 0 R , . . . , − r n − 1 R , ∣ r x ′ r 0 ′ , . . . , r x ′ r n − 1 ′ , ∣ r x ′ R , R 2 ) = w \begin{aligned}
v·L &= (k_0, ..., k_{n-1}, | r_x' r_0', ..., r_x' r_{n-1}', | r_x', 1 ) · L \\
&= (-r_0 R, ..., -r_{n-1} R, | r_x' r_0', ..., r_x' r_{n-1}', | r_x' R, R^2) = w
\end{aligned}
v ⋅ L = ( k 0 , ... , k n − 1 , ∣ r x ′ r 0 ′ , ... , r x ′ r n − 1 ′ , ∣ r x ′ , 1 ) ⋅ L = ( − r 0 R , ... , − r n − 1 R , ∣ r x ′ r 0 ′ , ... , r x ′ r n − 1 ′ , ∣ r x ′ R , R 2 ) = w
粗略计算(相关知识点在一篇很久远而且挺乱的文章 ):
∥ w ∥ ≈ 2 2 ∗ 328 σ ( L ) ≈ 2 ( 1024 + 328 + 1 ) n + 3 ∗ 328 2 n + 2 \begin{aligned}
\|w\| &≈ 2^{2*328} \\
\sigma(L) &≈ 2^{\frac{(1024+328+1)n + 3*328}{2n + 2}}
\end{aligned}
∥ w ∥ σ ( L ) ≈ 2 2 ∗ 328 ≈ 2 2 n + 2 ( 1024 + 328 + 1 ) n + 3 ∗ 328
若∥ w ∥ < σ ( L ) \|w\| < \sigma(L) ∥ w ∥ < σ ( L ) 即:
2 ∗ 328 < ( 1024 + 328 + 1 ) n + 3 ∗ 328 2 n + 2 4 ∗ 328 ( n + 1 ) < ( 1024 + 328 + 1 ) n + 3 ∗ 328 4 ∗ 328 n + 328 < ( 1024 + 328 + 1 ) n n > 328 1024 + 328 + 1 − 4 ∗ 328 = 328 41 = 8 \begin{aligned}
2*328 &< \frac{(1024+328+1)n + 3*328}{2n + 2} \\
4*328 (n+1) &< (1024+328+1)n + 3*328 \\
4*328 n + 328 &< (1024+328+1)n \\
n &> \frac{328}{1024+328+1 - 4*328} = \frac{328}{41} = 8
\end{aligned}
2 ∗ 328 4 ∗ 328 ( n + 1 ) 4 ∗ 328 n + 328 n < 2 n + 2 ( 1024 + 328 + 1 ) n + 3 ∗ 328 < ( 1024 + 328 + 1 ) n + 3 ∗ 328 < ( 1024 + 328 + 1 ) n > 1024 + 328 + 1 − 4 ∗ 328 328 = 41 328 = 8
算上”基准“的获取,总共访问10次Oracle就足够了,不过把15次全用完问题也不大。
最后就是LLL解出r ′ r' r ′ 代入求出s s 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 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 def matrix_overview (BB ): for ii in range (BB.dimensions()[0 ]): a = ('%02d ' % ii) for jj in range (BB.dimensions()[1 ]): if BB[ii, jj] == 0 : a += ' ' else : a += 'X' if BB.dimensions()[0 ] < 60 : a += ' ' print (a) from pwn import *rmo = remote('127.0.0.1' , 9006 ) rmo.readuntil(b'> mod = ' ) p = Integer(rmo.readline()) print (p)rmo.sendline(b'1' ) rmo.readuntil(b'> r = ' ) rx = Integer(rmo.readline()) rmo.readuntil(b'> d = ' ) dx = Integer(rmo.readline()) print (rx, dx)n = 14 r = [] d = [] for i in range (n): rmo.sendline(b'1' ) rmo.readuntil(b'> r = ' ) r += [Integer(rmo.readline())] rmo.readuntil(b'> d = ' ) d += [Integer(rmo.readline())] print (r[-1 ], d[-1 ]) R = 2 ^328 Mt = matrix(ZZ, 2 *n+2 ) for i in range (n): Ai = (d[i] * (rx - r[i]) + 1 ) % p Bi = (dx * (rx - r[i]) - 1 ) % p Ci = (rx - r[i]) % p Di = (d[i] - dx - d[i] * dx * (rx - r[i])) % p Bii = Bi.inverse_mod(p) AA = (Bii * Ai) % p BB = (Bii * Ci) % p CC = (Bii * Di) % p Mt[i, i] = -p * R Mt[n+i, i] = BB * R Mt[n+i, n+i] = 1 Mt[-2 , i] = AA * R Mt[-1 , i] = CC * R Mt[-2 , -2 ] = R Mt[-1 , -1 ] = R^2 matrix_overview(Mt) L = Mt.LLL() print (L[0 ])for i in range (n): try : assert L[0 ][i] % R == 0 ri_ = abs (L[0 ][i] // R) s = (Integer(d[i] + ri_).inverse_mod(p) - r[i]) % p except : print ('?%d' % i) continue print () print (s) rmo.sendline(b'2' ) rmo.sendline(bytes (str (s), encoding='utf-8' )) break rmo.interactive() rmo.close()
LockByLock·
题目:LockByLock.py(代码的main.py
)
这题其实没做完,赛后才知道Pollard’s kangaroo algorithm 可以直接解,原来wiki 上有,怪不得这么多解(逃
首先有一个知识点是,若a b > n a b>n ab > n 且知道a a a 、b b b 、a ( m o d n ) a \pmod n a ( mod n ) 和b ( m o d n ) b \pmod n b ( mod n ) ,那么就有
k a n = a − ( a ( m o d n ) ) k b n = b − ( b ( m o d n ) ) k_a n = a - (a \pmod n) \\
k_b n = b - (b \pmod n)
k a n = a − ( a ( mod n )) k b n = b − ( b ( mod n ))
于是通过计算
g c d ( a − ( a ( m o d n ) ) , b − ( b ( m o d n ) ) ) = g c d ( k a n , k b n ) = g c d ( k a , k b ) ⋅ n \rm{gcd}(a - (a \pmod n), b - (b \pmod n)) = \rm{gcd}(k_a n, k_b n) = \rm{gcd}(k_a, k_b) · n
gcd ( a − ( a ( mod n )) , b − ( b ( mod n ))) = gcd ( k a n , k b n ) = gcd ( k a , k b ) ⋅ n
就有机会恢复n n n .
类似地,若知道a ( m o d n ) a \pmod n a ( mod n ) 、b ( m o d n ) b \pmod n b ( mod n ) 、a 2 ( m o d n ) a^2 \pmod n a 2 ( mod n ) 和b 2 ( m o d n ) b^2 \pmod n b 2 ( mod n ) ,也可以通过
g c d ( ( a ( m o d n ) ) 2 − a 2 ( m o d n ) , ( b ( m o d n ) ) 2 − b 2 ( m o d n ) ) \rm{gcd}((a \pmod n)^2 - a^2 \pmod n, (b \pmod n)^2 - b^2 \pmod n)
gcd (( a ( mod n ) ) 2 − a 2 ( mod n ) , ( b ( mod n ) ) 2 − b 2 ( mod n ))
尝试恢复n n n 。
贴一个当时获取n n n 的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 from pwn import *rmo = remote('127.0.0.1' , 9006 ) rmo.readuntil(b'Alice: locked msg1 = ' ) fm1 = Integer(rmo.readline()) rmo.readuntil(b'Bob: locked msg2 = ' ) fm2 = Integer(rmo.readline()) rmo.readuntil(b'Alice: unlocked msg3 = ' ) fm3 = Integer(rmo.readline()) rmo.readuntil(b'Bob: lock lock, unlock lock!' ) o = 2 o2 = o^2 rmo.sendline(bytes (str (o), encoding='utf-8' )) rmo.readuntil(b'Alice: locked msg1 = ' ) om1 = Integer(rmo.readline()) rmo.readuntil(b'Bob: locked msg2 = ' ) om2 = Integer(rmo.readline()) rmo.readuntil(b'Alice: unlocked msg3 = ' ) om3 = Integer(rmo.readline()) rmo.readuntil(b'Bob: lock lock, unlock lock!' ) print ('Debug > om1 = %d' % om1)print ('Debug > om2 = %d' % om2)print ('Debug > om3 = %d' % om3)rmo.sendline(bytes (str (o2), encoding='utf-8' )) rmo.readuntil(b'Alice: locked msg1 = ' ) o2m1 = Integer(rmo.readline()) rmo.readuntil(b'Bob: locked msg2 = ' ) o2m2 = Integer(rmo.readline()) rmo.readuntil(b'Alice: unlocked msg3 = ' ) o2m3 = Integer(rmo.readline()) n = gcd(om1^2 - o2m1, om3^2 - o2m3) if len (bin (n))-2 > 2048 : if n % 2 == 0 : n //= 2 if n % 3 == 0 : n //= 3 assert len (bin (n))-2 == 2048 print ('Debug > n = %d' % n)rmo.close()
菜