攻防世界-不仅仅是RSA

一、题目
给出以下几个文件

py文件代码如下

二、解题思路
1、听C1,C2的音频, 由长短声很快确定是摩斯密码,上网一搜,果然有在线摩斯密码音频解密网站,上去解密即可

这里初步判断可能是密文

2、进一步分析代码

分析代码发现这就是一个简单的RSA加密算法,并且有两个不同公钥的RSA加密过程,
但是可以发现他们的n中都有一个共同的q,由于p和q都是素数,所以可以从求解n1和n2的最大公因式入手。

3、但是公钥都不知道,这时想起还有两个文件没有用到,这不就是公钥吗

上网一查发现“.pem”文件常常用来保存公钥,用文件查看器可以看到里面的公钥用base64的格式进行编码。

但是这里不进行解码,因为公钥只是一些无序的二进制数据,并没有什么实际的文本意义,python的Crypto.PublicKey库中的RSA模块提供公钥文件读取函数,直接调用即可读取入的公钥有n和e,用图示的办法可以分别调出它们。

在安装Crypto库后出现了仍然无法调用库函数的情况

上网查了一下找到了解决办法:参考文章

4、有了n1和n2,现在可以利用欧几里得辗转相除法求取n1和n2的最大公约数q,这样p1和p2就有了,一切都变得简单。

5、由于n=p*q,求解出q后就可以求解p1和p2,需要注意的是使用整除符号“//”而不是除号“/”。

解释:

  • 普通除法 /:会返回一个浮动类型的结果,即使除数能够整除。
  • 整数除法 //:返回一个整数结果,去掉小数部分。

这里可以验证一下,如果使用“/”,可以看到p的类型是浮点数,而“//”的结果中p的类型是整数:

6、然后就是求解逆元d1和d2,最后利用d1和d2进行解密。第三方库中的inverse()函数就是求解逆元d的函数,参数为e和欧拉数phi,参数只能接收整数,这也是之前需要使用整除符号的原因。

phi = (p-1)*(q-1) 这时RSA的常识

7、利用私钥(n1,d1)和(n2,d2)解出明文m1和m2,再拼接即可得出flag

解密:m = e^d mod n

这里需要注意Crypto.Util.number库中的long_to_bytes模块,它是用来把这么一大串长数字转化为字节串显示。

补充:

  • 字节串(bytes)是二进制数据的原始表示,每个字节表示一个数字值,范围从0到255。它们用于存储图像、音频、视频、加密密文等非文本类型的数据。这些字节可以是打印字符的编码,也可以是无法显示的控制字符或其他数据。
  • 字节串中的每个字节都可以用 \x 后跟十六进制数字的形式表示,这些字节值不一定对应于可打印字符。
  • print函数在打印字节串的时候会默认使用utf-8进行解码,如果字节串不能被utf-8正确解码,就会出现如下形式:

    这时可能要如果出现这种情况,要么就是解密出现错误,要么就是密文并不是简单的文本形式,需要进行特殊的转化。

8、脚本代码

from Crypto.PublicKey import RSA
from Crypto.Util.number import inverse,long_to_bytes


with open("pubkey1.pem","rb") as f:
    pk1_bit= f.read()
with open("pubkey2.pem","rb") as f:
    pk2_bit =f.read();

pk1 = RSA.importKey(pk1_bit)
pk2 = RSA.importKey(pk2_bit)

n1 = pk1.n
e1 = pk1.e
n2 = pk2.n
e2 = pk2.e

c1 = 4314251881242803343641258350847424240197348270934376293792054938860756265727535163218661012756264314717591117355736219880127534927494986120542485721347351
c2 = 485162209351525800948941613977942416744737316759516157292410960531475083863663017229882430859161458909478412418639172249660818299099618143918080867132349

#求解两数的最大公约数
def gcd(a,b):
    while(b!=0):
        r=a%b
        a=b
        b=r
    return a

p = gcd(n1,n2)
q1 = n1//p
q2 = n2//p

phi_1 = (p-1)*(q1-1)
phi_2 = (p-1)*(q2-1)

d1= inverse(e1,phi_1)
d2= inverse(e2,phi_2)

m1_bit = pow(c1,d1,n1)
m2_bit = pow(c2,d2,n2)

m1 = long_to_bytes(m1_bit)
m2 = long_to_bytes(m2_bit)


print(m1+m2)

9、最终答案
b'UNCTF{ac01dff95336aa470e3b55d3fe43e9f6}'

posted @ 2024-12-01 02:18  wyuu101  阅读(22)  评论(0编辑  收藏  举报