RSA之Coppersmith攻击
- 参考博客:Coppersmith 攻击
- 参考博客:RSA中coppersmith定理的应用条件-CSDN博客
介绍
Coppersmith可以用于求多项式的小根,经常用于 RSA 攻击中“已知某些二进制位,求剩余位”这一类问题。
方程的思想
coppersmith攻击主要用到的数学思想就是方程的思想。这边我们就先来举一个例子:
1 | # 这边我们有一个512位的大数p |
- 对于一个阶为
e的多项式f可以求得以下满足条件的方程:coppersmith攻击就是,在模n的意义下,快速求出$ n^{\frac{1}{e}} $以内的根,在我们给的例子中就是解方程中的x。- 给定$ \beta $ ,快速求出模某个
b意义下较小的根,其中$b ≥ n^\beta$ - 本质上就是解满足条件的方程,我们所需要做的就是去寻找条件和构造方程,本质上还是数学,如果只是要套公式的话,还是和算法没太大关系
相关论文
- 对于
Coppersmith攻击,这个攻击的具体原理与格有关。并且目前为止Coppersmith攻击确实是比较重要的一个攻击。 - 而
Coppersmith攻击之所以被称为Coppersmith攻击,是因为这个攻击方式是Don Coppersmith这个人发表的一篇论文,说明了这个攻击,所以后来这个攻击方式就被称为Coppersmith攻击。 - 这篇论文虽然发表时间已经过了很久,但还是很值得一读的(之后知识储备足够了,肯定会去读一读这篇论文),这篇论文就先放在这里。
- 之后其他人在
Coppersmith攻击的基础之上提出了二元Coppersmith攻击。论文如下:
sage实现copper
-
在
sage中应用coppersmith定理的函数有两个:small_roots、coppersmith_howgrave_univariate -
这边我们只介绍
small_roots这个函数,而coppersmith_howgrave_univariate好像在新版的sagemath好像不存在(总之我没找到,之后找到了再写)。 -
这里就先来介绍一下
small_roots的使用。使用的模版如下:- 这里
n其实就是一个整数 PR.<x> = PolynomialRing(Zmod(n))- 定义一个在模n下的多项式整环,其实也就是一个多项式。这个多项式有一个特点就是它的系数不会超过n。
- 并且这个多项式使用
x作为变量,就像这样$f(x)=a_nx^n+a_{n-1}x^{n-1}+…+a_1x+a_0$
- 然后
f =就相当于我们定义一个关于x的多项式(这一步就相当于确定关于x的方程) f = f.monic():将这个多项式f转换为首项为1的。注意这一步是必须的,否则最高次数项不是1运行后会报错。- 之后就是
out = f.small_roots(X=2^n,beta=0.5)寻找最小的根。这边有两个参数,要重点说明一下:- 这里的参数
X表示限定我们要求的根的上限,上限太高可能就会找到其他解,或者是稍微浪费算力,这边可以在源码的倒数第三行可以发现。 - 而
beta表示的是我们寻找的根的下限。beta必须满足0<=beta<1否则会报错。在下面源码中第156行会有判断。而beta的下限具体作用会展现在源码的最后一行,程序得到的根会在返回之前会先排除小于$n^{\beta}$的解。 - 总的来说
small_roots是求解$n^{\beta}≤r≤X$范围内的根。所以有的时候我们就需要调整好我们传递的参数,否则就会导致small_roots返回的是空列表。beta这个参数还是比较奇妙的,有时候$n^\beta$有500位,但是我们还是可以得到200位的根这里先填个坑,之后再来解释一下,总之beta取值一定要在某个正确的范围内,否则会返回空列表(在不了解beta的取值原理时,我们其实都可以采取爆破的策略beta取值其实也就100种可能)
- 这里的参数
- 这里
1 | n = |
题型1_已知高位
题目1_已知m高位求低位
- 题目:
1 | from Crypto.Util.number import * |
- 在这种情况下,由于我们用于加密的
m比较大,所以这题就不能使用低加密指数的方法来解。并且这题我们已经知道了m的高440位,这时我们就需要想办法去求m的低72位。我们先利用方程的思想,将m使用方程表达出来。
$$
\begin{array}{l}
设x表示m的低72位,而leak表示的是m的高440位\
这时我们就有\
m = leak + x\
会有如下等式\
c \equiv m^3\equiv(leak+x)^3~mod(~n~)\
用同余性质可得\
m^3-c \equiv (leak+x)^3-c\equiv 0 ~mod(~n~)\
此时我们就可以得到关于x的多项式系数,最高次为3\
经过验证得到n^{\frac{1}{3}}的bit位为342位,而我们求的x为72位\
这就说明我们可以使用coppersmith攻击快速求根
\end{array}
$$
- 接下来我们就来使用
coppersmith求解,这里比较简单的就是,我们在使用small_roots()这个函数的时候,并不需要调整参数。而是直接调用即可。主要是因为我们构造出的方程刚好是$(leak+x)^3-c\equiv 0 ~mod(~n~)$,所以这题使用coppersmith攻击主要是求在模n的意义下,$ n^{\frac{1}{e}} $以内的根
1 | from Crypto.Util.number import * |
- 目前还不知道
coppersmith攻击原理,如果要会用的话,过程其实就是这几步:- 第一步,确定多项式环中的模数。
- 第二步,确定多项式。
- 第三步,确定
coppersmith攻击的条件是否满足。 - 第四步,调用
small_roots()函数求解方程。
题目2_已知p的高位求低位
- 题目如下:
1 | from Crypto.Util.number import * |
- 这题的思路与题目一的思路比较像,但是却比题目一简单。因为这题直接设
p的低位为未知数即可。这边就给出一张图片

- 推导如下:
$$
\begin{array}{l}
这题我们就可以直接设p的低位为x\
这样我们就可以表示出p\
p = leak << 200 + x=p_{high}+x\
我们可以从题目得到x的大小为200位\
所以我们规定X(即根的上限)为2^{200}次幂\
而\beta取0.13到0.50都可以
\end{array}
$$
- 解密就像这样即可,因为我们这时使用的是
coppersmith攻击中,给定$ \beta $ ,快速求出模某个b意义下较小的根,其中$b ≥ n^\beta$。所以我们必须要指定small_roots中的参数
1 | from Crypto.Util.number import * |
题目3_已知d的高位
题目4_已知dp高位
- 题目如下:
1 | from Crypto.Util.number import * |
题型2_已知高低位
题目1_已知p高位和q低位
-
题目来源:[鹤城杯 2021]BabyRSA。[鹤城杯 2021]BabyRSA | NSSCTF
-
题目附件如下:
1 | from Crypto.Util.number import getPrime, bytes_to_long |
- 这题本质上还是已知p的位数,求利用
small_roots求解p,其中我们是可以知道p的高300位的。而根据hint2我们其实可以求出p的低265位。推到过程如下:
$$
\begin{array}{l}
其实我们已知n = p*q
\此时我们设p_{low}为p的低265位,p_r为p的剩余位数
\所以有p = 2^{265}*p_r + p_{low}
\同理得q = 2^{265}q_r + q_{low}
\可得到n = pq=(2^{265}p_r+p_{low})(2^{265}*q_r+q_{low})
\展开可以得到如下式子:
\n=2^{530}p_rq_r+2^{265}p_rq_{low}+p_{low}*2^{265}*q_r+p_{low}*q_{low}
\这时我们将n模一个2^{265}就会得到
\n\equiv p_{low}q_{low}~mod~(2^{265})
\此时我们已知n和q_{low},计算出p_{low}就没有问题
\p_{low}\equiv nq_{low}^{-1}~mod(2^{265})
\end{array}
$$
- 计算出
p的低256位之后,我们就可以列方程了
$$
\begin{array}{l}
p的剩余为使用x表示,则p可以列出方程\
p = p_{high}2^{724}+x2^{265}+p_{low}
\在然后我们大致确定一下x的位数
\1024-300-265=459
\end{array}
$$
- 此时我们就可以使用coppersmith进行求解,但是如果对这个方程直接用
small_roots求解,是解不出来的,这时我们对2**265位--2**271位进行爆破。同时让small_roots()传入的X参数为459-6,传入的beta值在0.44--0.38之间才能求解出正确答案 - exp如下:
1 | import libnum |
题型3_已知低位
题目1_已知d的低位
题目2_已知dp的低位
题目3_已知dp的高位
题型4_灵活构造方程
- 有的时候
coppersmith攻击的方程不是很好找到,需要进行构造,需要掌握并熟练运用转换与化归这一数学思想。还需要比较多的定理和技巧作为辅助操作。 - 接下来就写几个例题,找一找感觉。心里的一点想法:对数学的热爱并不是单纯的热爱,而是比较功利性的热爱,初中的数学考试成绩使得我陷入了幻想,并对数学产生了带有功利性的兴趣。但是这样的兴趣必然会在一次次数学考试分数不高之后被磨灭。并且自己也没有花太多时间探索数学,导致一些思维能力也没培养上来,到了高中由于时间紧,对数学的探索就更少了,所以到大学对数学就没太大兴趣。其实初一的时候,我爸妈想给我买数学练习,结果买回来的是初一奥数,从里面我就了解到了同余(实际上我直接把同余当做了恒等符号)。对于这本书也只是翻一翻,看看题目解析,对每一题实际上并没有动手去算、没有探索,也没有每周花一天去死磕一题(周末经常在玩中内耗,也没通过电脑了解更多东西),当时甚至连那边出现的平方差公式都不认识(人教版初中教材初二才教平方差公式)所以初高中过得比较平凡(和大部分人一样)
- 回归正题,就介绍一下这种题型。
题目1_共模攻击构造
- 题目来源:[SWPUCTF 2021 新生赛]crypto3 | NSSCTF
- 当然这种题型还有另外一种不使用构造方程用
Coppersmith打,也可以使用同余加上费马小定理解决,这个解法后面也会给出推导 - 题目如下:
1 | from gmpy2 import * |
- 这题表面上看是一个共模攻击,但是附件中并没有给加密指数
p、q这时共模攻击的方法就无法使用了。此时我们就要走别的路子了。
其他
题目1_dp泄露通解
-
题目的代码如下:
1 |
|
题目2_d比较小_Boneh_and_Durfee_attack
- d比较小的话是有两种攻击方法的,Boneh and Durfee attack这种攻击方式就是使用的
Coppersmith方法。 - d比较小还有一种攻击方式就是维纳攻击,这两个攻击都是已知d,且d比较小。
- 当时使用Boneh and Durfee attack会比较好一点,因为此时d满足的范围会更大,但是Boneh and Durfee attack攻击的代码比较难实现(虽然可以直接套轮子)。如下图所示:

- 而维纳攻击的条件如下:

small_roots函数源码
- 函数源码如下:
1 | def small_roots(self, X=None, beta=1.0, epsilon=None, **kwds): |

