解密RSA加密文件(equation)

0x01 题目来源

http://mslc.ctf.su/wp/0ctf-2016-quals-equation-crypto-2-pts/

0x02 解题思路

1、打开文件夹,其中有这样的一个私钥片段,这就需要进行分析,这个片段里面究竟是哪些内容。
-----BEGIN RSA PRIVATE KEY-----
[masked]
Os9mhOQRdqW2cwVrnNI72DLcAXpXUJ1HGwJBANWiJcDUGxZpnERxVw7s0913WXNt
V4GqdxCzG0pG5EHThtoTRbyX0aqRP4U/hQ9tRoSoDmBn+3HPITsnbCy67VkCQBM4
xZPTtUKM6Xi+16VTUnFVs9E4rqwIQCDAxn9UuVMBXlX2Cl0xOGUF4C5hItrX2woF
7LVS5EizR63CyRcPovMCQQDVyNbcWD7N88MhZjujKuSrHJot7WcCaRmTGEIJ6TkU
8NWt9BVjR4jVkZ2EqNd0KZWdQPukeynPcLlDEkIXyaQx
-----END RSA PRIVATE KEY-----

要想了解RSA私钥的具体构成,可以参考以下链接:
http://blog.sina.com.cn/s/blog_4fcd1ea30100yh4s.html

我将已知的片段base64解码,其16进制表示如下:

3acf6684e41176a5b673056b9cd23bd832dc017a57509d471b(属于q)

0241

00d5a225c0d41b16699c4471570eecd3dd7759736d5781aa7710b31b4a46e441d386da1345bc97d1aa913f853f850f6d4684a80e6067fb71cf213b276c2cbaed59(属于exponent1)

0240

1338c593d3b5428ce978bed7a553527155b3d138aeac084020c0c67f54b953015e55f60a5d31386505e02e6122dad7db0a05ecb552e448b347adc2c9170fa2f3(属于exponent2)

0241

00d5c8d6dc583ecdf3c321663ba32ae4ab1c9a2ded6702691993184209e93914f0d5adf415634788d5919d84a8d77429959d40fba47b29cf70b943124217c9a431(属于coefficient)
2、理论背景

因为:

e * dp == 1 (mod (p-1)) = d mod (p-1)  
e * dq == 1 (mod (q-1)) = d mod (q-1)  
q * qi == 1 (mod p) = q^-1 mod p 

所以:

(e * dp -1)/k +1 == (p)
(e * dq -1)/j +1 == (q)
(q * qi -1)/l == (p)
3、编写代码

已知的片段是

q = 0x3acf6684e41176a5b673056b9cd23bd832dc017a57509d471b
dp = 0x00d5a225c0d41b16699c4471570eecd3dd7759736d5781aa7710b31b4a46e441d386da1345bc97d1aa913f853f850f6d4684a80e6067fb71cf213b276c2cbaed59
dq = 0x1338c593d3b5428ce978bed7a553527155b3d138aeac084020c0c67f54b953015e55f60a5d31386505e02e6122dad7db0a05ecb552e448b347adc2c9170fa2f3
qi = 0x00d5c8d6dc583ecdf3c321663ba32ae4ab1c9a2ded6702691993184209e93914f0d5adf415634788d5919d84a8d77429959d40fba47b29cf70b943124217c9a431

首先根据上面的式子计算q:

for j in range(N,1,-1):
    q_ = (e * dq -1)/j +1
    if "3acf6684e41176a5b673056b9cd23bd832dc017a57509d471b" in str(hex(q_)):
        print q_, j

得到的q_(即想要的q):
12502893634923161599824465146407069882228513776947707295476805997311776855879024002289593598657949783937041929668443115224477369136089557911464046118127387
接下来先定义两个函数用来求模逆:

def egcd(a, b):
    if a == 0:
        return (b, 0, 1)
    else:
        g, y, x = egcd(b % a, a)
        return (g, x - (b // a) * y, y)

def modinv(a, m):
    g, x, y = egcd(a, m)
    if g != 1:
        #raise Exception('modular inverse does not exist')
        return -1
    else:
        return x % m

然后需要求p:

M = 1
N = 100000
for k in range(M,N,1):
    p1 = (dp * 0x10001-1)/k+1
    m = modinv(q_, p1)
    if m == qi:
        print "p_:",p1, k
        sys.exit(1) 

得到的p如下:
12883429939639100479003058518523248493821688207697138417834631218638027564562306620214863988447681300666538212918572472128732943784711527013224777474072569
由此就可以得到n,并利用上面的模逆函数得到d。
print modinv(e, f(n))

d = 12441639692099655517376308833932392670257420848582256919212988552216677594845086557017745931627109670194928630671056032860651983223301005431608062335676428430110171020554477490159485308455680772826276447201841772149055876380443034602731403064627486237285806604612267999273183028007861118868108999965277036321

0x03 获取FLAG

到目前为止,已经得到了我想要的的参数值,那么就可以开始解密文件:

fp = open('flag.enc','rb')
x = fp.read()
print x.encode('hex')
print int(x.encode('hex'),16)

d = 12441639692099655517376308833932392670257420848582256919212988552216677594845086557017745931627109670194928630671056032860651983223301005431608062335676428430110171020554477490159485308455680772826276447201841772149055876380443034602731403064627486237285806604612267999273183028007861118868108999965277036321
n = 161080154188292201430717335450301702574211890587423028785946588452513709903864566907797711402814280216429284407010865117658741411399738837015270166197792615276511302372234182990420185803542388458087342116253675425489502589540709488892694405415013333511961708962693793627275736479090319881934245022826824347203

def str2num(s):
    return int(s.encode('hex'),16)
def num2str(n):
    d = ('%x' % n)
    if len(d) % 2 == 1:
        d = '0' + d
    return d.decode('hex')

x = 22950838243355051507735476344130216859576434035671340145571506267533078667102139095850647801394751140978861909254514064618936561207518062388831395696067732470866299734394736771987882752821762750879035746758561421031626630277903489313416714548078647228307878986111206166442661515283012588864037384850878485926
print num2str(pow(x,d,n))

最后得到flag:
这里写图片描述

0x04 参考链接

http://blog.sina.com.cn/s/blog_4fcd1ea30100yh4s.html
https://0day.work/0ctf-2016-quals-writeups/
http://mslc.ctf.su/wp/0ctf-2016-quals-equation-crypto-2-pts/

在做题的过程中发现一些相关资源可能本题没有用到:
解密文件:
https://www.cnblogs.com/alittlebitcool/archive/2011/09/22/2185418.html
libnum库的安装方法
http://www.cnblogs.com/pcat/p/7225782.html

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值