Extremely hard RSA 低加密指数攻击

题目说明

没想到RSA4096都被你给破了,一定是我的问题,给了你太多信息,这次我只给你一个flag的加密值和公钥(Extremely hard RSA),仍然是RSA4096,我就不信你还能解出来。
文件链接: https://pan.baidu.com/s/1NwANbbs3eVcD7bpcmVqzmA 提取码: 6i5j

问题分析

首先需要了解一下RSA的加密原理,可以看一下这篇博客,讲得很清楚
https://blog.csdn.net/u014044812/article/details/80866759

这里我只贴部分公式。m: 明文,c: 密文,(n, e): 公钥,(n, d): 私钥
加密: m e ≡ c ( m o d   n ) m^e≡c(mod\ n) mec(mod n)
解密: c d ≡ m ( m o d   n ) c^d≡m(mod\ n) cdm(mod n)
其中c, n, e是已知条件,m是我们要求取的。

题目中给的pubkey.pem是base64编码后的公钥,我们使用openssl命令提取其中的n和e,当然也可以用其他方式提取。
openssl rsa -pubin -text -modulus -in pubkey.pem

找到关键部分: Exponent: 3 (0x3) 和 Modulus=B0BEE5E3E……,其中Exponent就是公钥中的e,Modulus就是公钥中的n。e是加密者自定义的,一般越大越安全,这里e=3指引了我们破解的方式,也就是低加密指数攻击。

低加密指数攻击

现在加密公式变成了: m 3 ≡ c ( m o d   n ) m^3≡c(mod\ n) m3c(mod n),其中 c   m o d   n c\ mod\ n c mod n可以直接求出,我们令MOD = c   m o d   n =c\ mod\ n =c mod n,则 m 3   m o d   n = m^3\ mod\ n= m3 mod n=MOD,再变换一下得出:
m 3 = k n + m^3=kn+ m3=kn+MOD, k = 0 , 1 , 2 , 3 k=0,1,2,3 k=0,1,2,3……
m = ( k n + m=(kn+ m=(kn+MOD ) 1 / 3 )^{1/3} )1/3 k = 0 , 1 , 2 , 3 k=0,1,2,3 k=0,1,2,3……
由于 m m m 也是整数,所以我们只需找到一个 k k k 使得 m m m 为一个整数即可。并且因为 e = 3 e=3 e=3,只需要开三次方,可以在有限时间内穷举出 k k k。这样我们便可以绕过私钥,绕过解密函数,直接获得明文 m m m

使用Python编码求解

# python3.6
# 把获得的n粘过来,加一个0x表示十六进制整数。或者也可以用python提取pubkey.pem中的n和e
n = 0xB0BEE5E3E9E5A7E8D00B493355C618FC8C7D7D03B82E409951C182F398DEE3104580E7BA70D383AE5311475656E8A964D380CB157F48C951ADFA65DB0B122CA40E42FA709189B719A4F0D746E2F6069BAF11CEBD650F14B93C977352FD13B1EEA6D6E1DA775502ABFF89D3A8B3615FD0DB49B88A976BC20568489284E181F6F11E270891C8EF80017BAD238E363039A458470F1749101BC29949D3A4F4038D463938851579C7525A69984F15B5667F34209B70EB261136947FA123E549DFFF00601883AFD936FE411E006E4E93D1A00B0FEA541BBFC8C5186CB6220503A94B2413110D640C77EA54BA3220FC8F4CC6CE77151E29B3E06578C478BD1BEBE04589EF9A197F6F806DB8B3ECD826CAD24F5324CCDEC6E8FEAD2C2150068602C8DCDC59402CCAC9424B790048CCDD9327068095EFA010B7F196C74BA8C37B128F9E1411751633F78B7B9E56F71F77A1B4DAAD3FC54B5E7EF935D9A72FB176759765522B4BBC02E314D5C06B64D5054B7B096C601236E6CCF45B5E611C805D335DBAB0C35D226CC208D8CE4736BA39A0354426FAE006C7FE52D5267DCFB9C3884F51FDDFDF4A9794BCFE0E1557113749E6C8EF421DBA263AFF68739CE00ED80FD0022EF92D3488F76DEB62BDEF7BEA6026F22A1D25AA2A92D124414A8021FE0C174B9803E6BB5FAD75E186A946A17280770F1243F4387446CCCEB2222A965CC30B3929

# 打开flag.enc,将字节串转换为整数
with open('flag.enc', 'rb') as f:
	hex_c = f.read()
c = int.from_bytes(hex_c, byteorder = 'big')

# 计算 c mod n
mod = c % n

# 引入gmpy2库用于求n次方根
import gmpy2

# 写一个测试函数,k在i,j范围内测试立方根
def test(i, j):
	for k in range(i, j):
		res, is_exact = gmpy2.iroot(k * n + mod, 3)
		if is_exact:
			print(k, res)

# 引入多进程库,由于GIL的存在,cpython只能在进程级别上并行
import multiprocessing

# 开始遍历
# 我的CPU是8个逻辑核,所以开8个进程,每个进程分配到18750000个。
for i in range(0, 150000000, 18750000):
	p = multiprocessing.Process(target = test, args = (i, i + 18750000))
	p.start()

我用的 2.3 GHz Intel Core i5 四核八线程 CPU在3分钟内跑出结果,就可以手动终止程序了,没必要全部跑完。
i = 118719488 i=118719488 i=118719488 时求出

m = 440721643740967258786371951429849843897639673893942371730874939742481383302887786063966117819631425015196093856646526738786745933078032806737504580146717737115929461581126895844008044713461807791172016433647699394456368658396746134702627548155069403689581548233891848149612485605022294307233116137509171389596747894529765156771462793389236431942344003532140158865426896855377113878133478689191912682550117563858186

然后将m转化为字符串格式

l = []
while m != 0:
	m, b = divmod(m, 256)
	l.insert(0, chr(b))
print(''.join(l))

打印出明文:
Didn’t you know RSA padding is really important? Now you see a non-padding message is so dangerous. And you should notice this in future.Fl4g: PCTF{Sm4ll_3xpon3nt_i5_W3ak}

PS: 明文中说的padding指需要加密的内容很短时,填充一些随机字符可以增加破解难度,尤其是在e取很小的时候。

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值