本文介绍了在CTF比赛中密码学中常用的工具及python库:简要讲解了下载方法,常用的使用方法。
RSA常用工具
RSAtool
任意给定两个素数(p,q)或者(模数n,私钥d)都可以计算出RSA(p,q,n,d,e)及RSA-CRT (dP, dQ, qInv)
-
返回参数可以以pem或der文件格式保存私钥文件
下载
-
git clone https://github.com/ius/rsatool.git
-
cd rsatool
使用
-
根据p,q生成私钥文件key.pem
python rsatool.py -f PEM -o key.pem -n 13826123222358393307 -d 9793706120266356337
Using (n, d) to initialise RSA instance n = 13826123222358393307 (0xbfe041d1197381db) e = 65537 (0x10001) d = 9793706120266356337 (0x87ea3bd3bd0b9671) p = 4184799299 (0xf96ef843) q = 3303891593 (0xc4ed6289) Saving PEM as key.pem
-
根据(p,q)生成key.der
python rsatool.py -f DER -o key.der -p 4184799299 -q 3303891593
Using (p, q) to initialise RSA instance n = 13826123222358393307 (0xbfe041d1197381db) e = 65537 (0x10001) d = 9793706120266356337 (0x87ea3bd3bd0b9671) p = 4184799299 (0xf96ef843) q = 3303891593 (0xc4ed6289) Saving DER as key.der
openssl
openssl可以查看公钥得到n和e,也可以利用私钥文件解密公钥加密的内容
下载
-
kail中自带
-
windows下可下载:OpenSSL-Win32
使用
-
查看公钥文件
openssl rsa -pubin -in pubkey.pem -text -modulus -
解密
rsautl -decrypt -inkey private.pem -in flag.enc -out flag
整数拆分工具
网站拆分:http://factordb.com/
命令行拆分:factordb-pycli,借用 factordb 数据库:https://github.com/ryosan-470/factordb-python
下载
FactorDB存储了已经知道的整数的拆分,这个工具可以在命令行上使用,对python2和python3也适用
-
本地对应pip下载即可:
pip3 install factordb-python -
更新factordb-python
pip3 install --upgrade factordb-python
使用
-
命令行使用
C:/Users/fishmouse>factordb 16
2 2 2 2
-
获得更多信息:
C:/Users/fishmouse>factordb --json 16
{"id": "http://factordb.com/api/?id=2", "status": "FF", "factors": [2, 2, 2, 2]}
-
FacotrDB库的使用
from factordb.factordb import FactorDB f = FactorDB(16)
f.get_factor_list()
[]
f.connect()
<Response [200]>
f.get_factor_list()
[2, 2, 2, 2]
f.get_factor_from_api()
[['2', 4]]
f.get_status()
'FF'
yafu本地拆分
windows下使用
xxx/yafu-1.34> ./yafu-x64.exe
factor(21)
RSA常用python库
gmpy2
windows下下载
-
whl文件形式下载,下载对应python版本的whl文件:https://www.lfd.uci.edu/~gohlke/pythonlibs/
pip3 install gmpy2-2.0.8-cp37-cp37m-win_amd64.whl
kail中下载
下载gmpy2这个库还需要一些相应的环境mpfr和mpc
-
首先下载mpfr,因为要下载mpc必须先下载mpfr
root@kali:~# wget https://www.mpfr.org/mpfr-current/mpfr-4.1.0.tar.bz2
若失败到官网:https://www.mpfr.org/mpfr-current查看最新root@kali:~# tar -jxvf mpfr-4.1.0.tar.bz2root@kali:~# cd mpfr-4.1.0root@kali:~/mpfr-4.1.0# ./configureroot@kali:~/mpfr-4.1.0# make && make check && make install -
下载mpc
root@kali:~# wget ftp://ftp.gnu.org/gnu/mpc/mpc-1.1.0.tar.gzroot@kali:~# tar -zxvf mpc-1.1.0.tar.gz && cd mpc-1.1.0root@kali:~/mpc-1.1.0# ./configureroot@kali:~/mpc-1.1.0# make && make check && make install -
下载gmpy2
root@kali:~# pip3 install gmpy2
常用函数
gmpy2.gcd最大公约数
import gmpy2 gmpy2.gcd(2,4)
mpz(2)
gmpy2.invert求逆元
gmpy2.invert(5,26)
mpz(21)
gmpy2.gcdext求逆元
gmpy2.gcdext(5,26)#传入(a,b);返回最大公约数、x、y :g= ax+by
(mpz(1), mpz(-5), mpz(1))
gmpy2.iroot开次方根
gmpy2.iroot(4,2)
(mpz(2), True)
libnum
pip下载
pip3 install libnum
常用函数
libnum.gcd求最大公约数
import libnum libnum.gcd(2,4)
2
libnum.invmod求逆元
libnum.invmod(5,26)
21
libnum.xgcd扩展欧几里得
libnum.xgcd(5,26)# xgcd(a,b)返回:x,y,g ;ax+by=g
(-5, 1, 1)
libnum.s2n字符串转为整数
libnum.s2n("hell0")
448378203184
libnum.n2s整数转换为字符串
libnum.n2s(448378203184)
'hell0'
pycryptodome
pip下载
pip3 install pycryptodome
下载后,可以使用Crypto这个模块,注意点:在对应python下的库Lib/site-packages中crypto开头为小写时,将其改为Crypto即可
小结
整数到字符串(字节串的相互转换)
整数和字符串
# 字符串到整数 import libnum libnum.s2n("hello")
448378203247
# 整数到字符串 libnum.n2s(448378203247)
'hello'
整数和字节串
# 字节串到整数 from Crypto.Util.number import long_to_bytes,bytes_to_long bytes_to_long('hello'.encode())
448378203247
# 整数到字节串 long_to_bytes(448378203247)
b'hello'
素数产生
脚本
# 检测大整数是否是素数,如果是素数,就返回True,否则返回False # miller_rabin算法 import random def rabin_miller(num): s = num - 1 t = 0 while s % 2 == 0: s = s // 2 t += 1 for trials in range(5): a = random.randrange(2, num - 1) v = pow(a, s, num) if v != 1: i = 0 while v != (num - 1): if i == t - 1: return False else: i = i + 1 v = (v ** 2) % num return True def is_prime(num): # 排除0,1和负数 if num < 2: return False # 创建小素数的列表,可以大幅加快速度 # 如果是小素数,那么直接返回true small_primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997] if num in small_primes: return True # 如果大数是这些小素数的倍数,那么就是合数,返回false for prime in small_primes: if num % prime == 0: return False # 如果这样没有分辨出来,就一定是大整数,那么就调用rabin算法 return rabin_miller(num) # 得到大整数,默认位数为1024 def get_prime(key_size=1024): while True: num = random.randrange(2**(key_size-1), 2**key_size) if is_prime(num): return num print(get_prime(50))
602912217591119
libnum
import libnum libnum.generate_prime(30)
936552131
libnum.generate_prime_from_string("abc")
418262526581
Crypto.Util.number
from Crypto.Util.number import getPrime getPrime(30)
930767861
rsa库简单使用
密钥生成
import rsa (pubkey, privkey) = rsa.newkeys(128) pubkey,privkey
(PublicKey(210654150686773160921155565886246123127, 65537), PrivateKey(210654150686773160921155565886246123127, 65537, 45430608142070156598272456648718438625, 245259021963773848463, 858904797874827929))
rsa加密
m = "hello".encode('utf-8') rsa.encrypt(m,pubkey)
b']/xd6/xb2w/xc4/x89[/xfcu`/x0b&/xa0/xc9`/xd2'
rsa解密
rsa.decrypt(b']/xd6/xb2w/xc4/x89[/xfcu`/x0b&/xa0/xc9`/xd2',privkey)
b'hello'
公钥文件查看方式
openssl
openssl rsa -pubin -in pubkey.pem -text -modulus
rsa库
import rsa with open('publickey.pem',mode='rb') as f: keydata= f.read() pubckey = rsa.PublicKey.load_pkcs1_openssl_pem(keydata) pubckey.n pubckey.e
私钥文件生成方式
rsatool.py
python rsatool.py -f PEM -o prvkey.pem -p 4184799299 -q 3303891593
from Crypto.PublicKey import RSA
# coding=utf-8 import math import sys from Crypto.PublicKey import RSA rsa_components=(n,e,int(d),p,q) keypair=RSA.construct(rsa_components) private = open('private.pem', 'wb') private.write(keypair.exportKey()) private.close()
根据私钥文件读取公钥加密后密文方式
利用rsa库直接读
import rsa prikey = rsa.PrivateKey(n , e , d , p , q) with open("test.enc" , "rb") as fp: print(rsa.decrypt(fp.read(), prikey).decode())
利用openssl
OpenSSL> rsautl -decrypt -in test.enc -inkey private.pem
字符串异或
Crypto.Util import strxor
from Crypto.Util import strxor strxor(b"hhh",b"aaa")

湖南省郴州市 1F
这个rsatool挺实用的,之前比赛用过好几次
湖北省 B1
@ WaffleCone rsatool在CTF里真香,特别是给p,q直接出私钥的时候,省好多事
天津市 2F
factordb网站有时候打不开啊,有替代方案吗
日本 B1
@ 精卫填海 factordb挂了的时候我一般用yafu本地跑,虽然慢点但稳
韩国 3F
libnum库那个字符串转换函数帮大忙了
浙江省湖州市 4F
openssl在win10下安装老是报错,折腾半天
吉林省长春市 B1
@ 钦原刺 win10装openssl真不如直接上wsl,省得折腾路径问题
陕西省宝鸡市 5F
yafu分解大数确实快,比手动算强多了
北京市 6F
gmpy2在kali装起来好麻烦,有简单点的方法吗
上海市 7F
pycryptodome那个大小写问题坑了不少人🤔
澳大利亚 8F
异或操作那块例子太简单了,能多讲点吗
北京市 B1
@ 绯月魔女 异或那块确实太简略了,比如多字节异或或者密钥复用的情况能展开说说吗?
北京市 9F
rsa库生成密钥速度怎样?大位数会不会很慢
上海市 10F
这些工具组合起来用效果确实不错
上海市 B1
@ 叛逆的吸管 rsatool配合openssl解密真的省事,不用自己手算参数了
浙江省台州市 11F
gmpy2装依赖是有点烦,不过装好一次后面就爽了
台湾省 12F
rsa.newkeys(1024)在我这笔记本上要等快10秒,大数生成确实吃性能
辽宁省朝阳市 13F
libnum的s2n和n2s比手写转换方便太多了,尤其处理flag的时候
山东省济宁市 B1
@ 樵夫刘 n2s有时候末尾多x00,记得strip()一下,不然flag对不上
广东省广州市 14F
win下openssl路径没配好就各种报错,建议直接用git bash带的
韩国 B1
@ GamerDude git bash自带openssl确实稳,不用折腾环境变量了
福建省厦门市 15F
pycryptodome改大小写那个坑我踩过,改完还得重启python环境才生效
北京市 16F
factordb打不开时也可以试试alpertron.com.ar/ECM.HTM,偶尔能分解小点的数
越南 17F
这些工具链串起来用才是王道,单个看平平无奇,组合起来直接解题飞起
江苏省徐州市 18F
这个rsatool真是解题神器,省事多了👍
广东省广州市 19F
用openssl配合rsatool直接解密flag,省掉手动拆分的麻烦,真的很赞
北京市 20F
factordb-pycli还能返回json,配合jq过滤,脚本化处理更顺手
北京市 21F
在Windows上rsa.newkeys(2048)会不会卡很久?
北京市 22F
gmpy2装依赖确实麻烦,但装好后算大数速度比纯Python快不少,别说是坑
黑龙江省哈尔滨市 23F
前几天刚用rsatool把p,q算出来,折腾了半天才成功
北京市 B1
@ 数据园丁 我也是卡在p,q输入格式上好久,后来才发现要十进制整数
浙江省杭州市 24F
openssl在win10的路径经常找不到,真是烦人
广东省汕头市 25F
看到有人把factordb和yafu一起用,分解速度飞起,简直是高手操作
印度 26F
大佬分享的在kali一次装好mpfr、mpc再装gmpy2的完整脚本,省了我好几小时的折腾,真是福音,强烈推荐给新人
韩国 27F
那如果只想要公钥的n和e,直接用openssl -pubin -text就行,还是要先转成pem格式?
广东省 28F
这个rsatool配合factordb确实好用,最近CTF全靠这俩组合
四川省眉山市 B1
@ TechNerd factordb挂了就用yafu本地跑,小点的数基本秒解
日本 29F
openssl在win10下确实容易出问题,建议直接用kali环境
陕西省榆林市 30F
这些库在CTF里确实实用,不过新手可能要花时间适应
重庆市 31F
libnum那个字符串转换在解密flag时经常用到
浙江省丽水市 32F
gmpy2装依赖是真的麻烦,但装好了速度确实快
北京市 33F
异或操作能再多举几个例子就好了🤔
北京市 34F
大佬能分享下yafu的详细用法吗?
韩国 35F
前几天刚用这些工具解了道RSA题,搞了整整一晚上
广东省广州市 36F
rsa库生成2048位密钥在我这要等半分钟,性能确实吃紧
内蒙古呼和浩特市 37F
win下用git bash带的openssl确实省事很多
印度 38F
factordb打不开的时候真抓狂,有没有离线替代方案?
美国 39F
yafu分解100位以内的数基本秒出,再大就看运气了
越南 40F
libnum的n2s有时候会多一个x00前缀,得手动strip一下
江苏省无锡市 41F
rsa库生成1024位在我老笔记本上快一分钟,急死人
江苏省南通市 42F
pycryptodome改大小写后不重启jupyter根本识别不了,血泪教训
北京市 43F
只给e和n的话,用openssl -modulus就能直接看模数吧?
浙江省舟山市 44F
gmpy2装完发现函数名和文档对不上,版本差异坑死新手
甘肃省兰州市 45F
rsa.newkeys(512)都卡成PPT,别提2048了😅
黑龙江省绥化市 46F
只给n和e的话,openssl -pubin -text -modulus直接出结果,不用转格式吧?
上海市浦东新区 47F
我之前也踩过pycryptodome大小写那个坑,改完不重启根本没用
上海市奉贤区 48F
gmpy2装依赖是烦,但iroot和invert这些函数真的快到飞起
江苏省盐城市 49F
factordb-pycli这玩意以前用过,还行
黑龙江省哈尔滨市 50F
libnum的s2n和n2s日常用得多
浙江省 B1
@ 社牛黑洞 libnum处理RSA数据很方便
北京市 51F
yafu在win下咋配环境变量啊?
广东省广州市 52F
rsatool.py生成私钥时-n和-d的参数顺序要注意吗?
浙江省 53F
@豆包 这库装起来太折腾了吧
荷兰 B1
@ 星环守护 装rsatool其实挺简单的,git clone下来就能用,pip安装factordb也很快。