0x00 RSA算法
RSA算法主要基于大整数分解这一困难问题设计.下面介绍一下加解密过程.
首先是需要用到的参数:
1 | m: 需要加密的消息即明文. |
然后是加解密关系式:
信息传播过程中,常将(e,N)作为公钥和密文c一同传播,而(d,N)作为私钥留在加密者和合法的接收者手中.选取并通过p*q计算N非常容易,但通过N还原p,q则是困难为题,这保证了该算法的安全性. 具体RSA基础可以参考:RSA基础
0x01 数学基础
模逆运算
如果(a*b) mod c == 1,那么a和b互为对方模c的模逆元/数论倒数,也写作$ a^(-1) \equiv b (mod c) $或$ a*b \equiv 1 (mod c) $
关于最大公约数有一个基本事实:给予两整数a、b,必存在整数x、y,使得a*x + b*y = gcd(a, b)
.从而当a、b互素时,有a*x + b*y = 1
,就有(a*x) mod b == 1
,所以x就是a对b的模逆元.
最大公约数有一个定义是:a和b的最大公约数g是a和b的线性和中的最小正整数.
常使用扩展欧几里得算法的一个python实现如下:
1 | def egcd ( a , b ): |
求模逆也可以使用gmpy2库的函数gmpy2.invert(a, b)
。
模运算法则
欧几里得算法
基本原理为:gcd(a,b) == gcd(b,a%b) while(b!=0)
和gcd(a,0) == a
python实现如下:
1 | # 递归版 |
扩展欧几里得算法
扩展欧几里得算法能够求出满足a*x+b*y = gcd(a,b)
的一组x,y.
python实现如下:
1 | # 递归版 |
中国剩余定理
具体算法可以参考上文提到的文章.
当mi两两互素的时候,可以使用如下脚本进行计算:
1 | def CRT(mi, ai): |
当mi不互素时,需要两两合并方程组.原理如下:
实现代码:
1 | def GCRT(mi, ai): |
0x02 常规攻击方法
由于RSA密码体系是基于大数分解这一困难问题设计,于是最先考虑到的便是分解N,然后根据加解密流程和关系式进行明文还原.
推荐工具
- 大数分解网站:位数较低的模数(长度一般小于100bits)可以在网站的库中查询分解结果:
大数分解网站 - 如果模数的位数较高,可以使用工具yafu进行分解,该工具集成了NFS等分解算法,适用于windows系统
- python环境下的libnum、gmpy2大数运算集成库
- github上的集成工具,具体使用方法在项目内部有详细说明:CTF-RSA-Tools
常用脚本
使用欧几里得算法求私钥d
Input_parameters: p, q, e
Output_parameters: d
1 | # 脚本一 |
1 | # 脚本二 |
加密脚本
Input_parameters: m, p, q, e
Output_parameters: c
1 | import gmpy2 as gp |
解密脚本
Input_parameters: c, p, q, e
Output_parameters: m
1 | import gmpy2 as gp |
文件型RSA攻击
所谓文件型RSA的题目,就是提供pubkey.pem和flag.enc文件.我们需要从pubkey.pem即证书文件中提取公钥信息,进行解密后生成private.pem私钥文件,然后对flag.enc文件进行解密得到结果.
常用命令如下(使用openssl对证书进行处理,使用rsatool.py对参数进行解密):
1 | openssl rsa -pubin -text -modulus -in warmup -in pubkey.pem |
0x03 基础CTF题目
已知p,q,e,求d
题目来源: buuctf RSA
题目描述:
1 | 在一次RSA密钥对生成中,假设p=473398607161,q=4511491,e=17 |
题目分析: 这是最基础的RSA题目,直接给出p和q的值.直接将所给信息写入脚本中即可求出d.将d按照flag提交要求进行进制转换后提交即可.
已知p,q,e,c,求m
题目来源: buuctf rsarsa
题目描述:
1 | Math is cool! Use the RSA algorithm to decode the secret message, c, p, q, and e are parameters for the RSA algorithm. |
题目分析: 该类题目已知p,q,e和c.先通过模逆算法求出d,再通过m = gp.powmod(c, d, p*q)
求出m即可
已知p,q,dp,dq,c,求m
题目来源: buuctf RSA1
题目描述:
1 | p = 8637633767257008567099653486541091171320491509433615447539162437911244175885667806398411790524083553445158113502227745206205327690939504032994699902053229 |
题目分析: 其中dp $\equiv$ d mod $\phi$(p), dq $\equiv$ d mod $\phi$(q).
我们发现这是一个同于方程组,使用中国剩余定理合并即可.但是发现p-1和q-1不互素,我们进行推导如下:
我们令$ d = (dp-dq)/dd((q-1)/dd)^{-1}(q-1) + dq $,从而合理运用所给参数得出最终结果.
脚本如下:
1 | import gmpy2 as gp |
已知e, n, dp, c,求m
题目来源: buuctf RSA2
题目描述:
1 | e = 65537 |
题目分析: 我们根据$ dp \equiv d mod \phi(p)$进行推导.
从而$ k\phi(p) + edp = k’(p-1)*(q-1) + 1 $
移项得:$ (p-1)(k’(q-1)-k) + 1 = edp $
我们通过枚举x可以计算出p-1,从而还原所有参数.脚本如下:
1 | import gmpy2 as gp |
文件型RSA
题目来源: buuctf RSA
题目描述: 下载附件之后发现有flag.enc和pub.key文件,于是使用openssl+rsatool解题.
题目分析: 题目中有.enc和.key文件,首先使用openssl的命令进行公钥提取.
我们可以得到e和n,在线分解n之后作为参数生成私钥.
最后使用private.pem与flag.enc生成flag文件.