BUUCTF 每日打卡 2021-7-20
引言
无
[NPUCTF2020]共 模 攻 击
题目给了两个加密程序 一个是加密hint:
1 | from gmpy2 import * |
另一个是加密flag:
1 | from gmpy2 import * |
乍一看,确实很像共模攻击,但是一看这个加密指数是p和q并且未知,就知道没那么简单 首先来解密hint 第一步容易想到用共模攻击解密被加密的hint 代码如下:
1 | import gmpy2 |
但下一步发现,加密hint的过程为c = pow(m, 256, p)
原本是想类似于经典的RSA解密 p的欧拉函数为p-1,然后参考[De1CTF2019]babyrsa或者EzRSA,利用\(gcd(256,p-1)\)解出d然后求解 但是发现\(gcd(256,p-1)=4\),无法用这种方法 只好找wp 原来直接用sympy库的nthroot_mod方法就行,该方法可以用来求解\(x^n \equiv a\space mod\space p\),其中\(n,a,p\)为已知数 那么,有这么好的方法,能不能直接用来求解RSA问题呢?当然是不行的 因为求解本题的\(m^{256} \equiv c\space mod\space p\)都要花上好几秒,求解RSA问题基本上不可能 这里附上nthroot_mod的源代码,感兴趣的师傅可以研究研究 完整解密代码如下: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23import gmpy2
import sympy
from Crypto.Util.number import *
# hint
e1 = 2303413961
e2 = 2622163991
c1 = 1754421169036191391717309256938035960912941109206872374826444526733030696056821731708193270151759843780894750696642659795452787547355043345348714129217723
c2 = 1613454015951555289711148366977297613624544025937559371784736059448454437652633847111272619248126613500028992813732842041018588707201458398726700828844249
p1 = 107316975771284342108362954945096489708900302633734520943905283655283318535709
n = 6807492006219935335233722232024809784434293293172317282814978688931711423939629682224374870233587969960713638310068784415474535033780772766171320461281579
gcd, s, t = gmpy2.gcdext(e1, e2)
if s < 0:
s = -s
c1 = gmpy2.invert(c1, n)
if t < 0:
t = -t
c2 = gmpy2.invert(c2, n)
c = gmpy2.powmod(c1, s, n) * gmpy2.powmod(c2, t, n) % n
print(c)
m = sympy.nthroot_mod(c, 256, p1)
print(long_to_bytes(m)) 提示m的位数小于400,有什么用吗? wp中说可以由此联想到Coppersmith 确实,在一些高位或低位泄露的题目中,Coppersmith是常用的手段,但是只知道位数小于400怎么用呢? wp一下的解题过程也确实没有用到Coppersmith 不过,wp给了Coppersmith定理一个比较通俗的解释:在一个\(e\)阶的以\(n\)为模的多项式\(f(x)\)中,如果有一个根小于\(n^{1/e}\),就可以运用一个O(log n)的算法求出这些根。其中的“阶”大概就是指(循环)群的阶 在这里重新推导一遍解题思路 由加密程序可得: \[
\begin{cases}
c_1 \equiv m^{p}\space mod\space n \equiv m^{p}\space mod\space pq \\
c_2 \equiv m^{q}\space mod\space n \equiv m^{q}\space mod\space pq
\end{cases}
\] 故\(\exists t_1\in \mathbb{Z}\),\(s.t. c_1 = m^p + t_1pq\) 于是有 \[
c_1 \equiv m^{p}\space mod\space p
\] 由费马小定理有 \[
m^{p}\equiv m\space mod\space p
\] 故 \[
c_1 \equiv m\space mod\space p
\] 同理,有 \[
c_2 \equiv m\space mod\space q
\] 故\(\exists k_1,k_2\in \mathbb{Z}\),\(s.t.\) \[
\begin{cases}
c_1=m+k_1p\\
c_2=m+k_2q
\end{cases}
\] 则 \[
\begin{cases}
(c_1+c_2)m=2m^2+(k_1p+k_2q)m \cdots (1)\\
c_1c_2=m^2+(k_1p+k_2q)m+k_1k_2pq \cdots (2)
\end{cases}
\] \((1)-(2)\)得: \[
(c_1+c_2)m-c_1c_2=m^2-k_1k_2pq=m^2-k_1k_2n
\] 移项,等式两边模\(n\),得: \[
m^2-(c_1+c_2)m+c_1c_2=k_1k_2n \equiv 0\space mod \space n
\] 所以只要在模\(n\)的情况下(或者说是在整数模\(n\)加法群中),求方程的根 参照wp,sage代码如下:
得到m直接long_to_bytes即可 结果为:
结语
摸了一天鱼,好累哦[doge] 关于sagemath的学习,官方文档看得挺累人的,推荐一个翻译的比较好的中文教程 油管上还找到一个入门教程,今年一月份的,用的是9.2版本,还比较新 希望继续坚持