攻防世界 Crypto进阶 Handicraft_RSA

1、题目

#!/usr/bin/python

from Crypto.Util.number import *
from Crypto.PublicKey import RSA
from secret import s, FLAG

def gen_prime(s):
    while True:
        r = getPrime(s) #生成一个素数r
        R = [r] #将r转换为列表
        t = int(5 * s / 2) + 1
        for i in range(0, t):
            R.append(r + getRandomRange(0, 4 * s ** 2))
            #生成一个0~(4 * s ** 2)的随机数加上r的值并加到列表R里面
        p = reduce(lambda a, b: a * b, R, 2) + 1
        #reduce()函数会对参数序列中元素进行累积。
        if isPrime(p):
            if len(bin(p)[2:]) == 1024:  #[2:]会截掉前面的'0b'
                return p

while True:
    p = gen_prime(s)
    q = gen_prime(s)
    n = p * q
    e = 65537
    d = inverse(e, (p-1)*(q-1))
    if len(bin(n)[2:]) == 2048:
        break

msg = FLAG
key = RSA.construct((long(n), long(e), long(d), long(p), long(q)))
for _ in xrange(s):  #循环加密s次
    enc = key.encrypt(msg, 0)[0]
    msg = enc

print key.publickey().exportKey()
print '-' * 76
print enc.encode('base64')
print '-' * 76

题目除了给了以上加密算法,还给出了公钥文件和密文;加密算法的部分操作已写上注释。

二、分析

1、个人认为其中p、q的生成算法写得虽然详细,但是解题过程却用不上,因为n可以直接被分解(后面又发现即使不分解n也能解题:从公钥中可以提取出私钥,也就不需要p、q了)
2公钥解析:首先将output.txt中的公钥部分复制出来保存为pubkey.pem,通过命令:

openssl rsa -pubin -text -modulus -in pubkey.pem

得到n和e。
3私钥提取:找到d的方法有两种:
(1)简单暴力的, n可以通过大数分解得到p、q,再对e求逆即得到d。
(2)网上看到其他师傅的做法:从公钥文件中提取出私钥来,命令:

python3 RsaCtfTool.py --publickey pubkey.pem --private

关于RsaCtfTool使用,这里再记录几个常用命令:

用法一:已知公钥文件和加密文件进行解密

python3 RsaCtfTool.py --publickey 公钥文件 --uncipherfile 加密的文件

用法二:已知公钥求私钥

python3 RsaCtfTool.py --publickey 公钥文件 --private

用法三:密钥格式转换
把PEM格式的公钥转换为n,e

python3 RsaCtfTool.py --dumpkey --key 公钥文件

把n,e转换为PEM格式

python3 RsaCtfTool.py --createpub -n 782837482376192871287312987398172312837182 -e 65537

三、解密脚本

从加密脚本可以看出来,flag进行了循环多次加密,在解密脚本中我们可以试着循环一个较大的数来解密(最后发现其实加密了20次)

from Crypto.Util.number import *
from Crypto.PublicKey import RSA
import gmpy2
import base64

pub = RSA.importKey(open('E:/CTF/XCTF/Crypto/RSA/Handicraft_RSA/Handicraft_RSA/handicraft_rsa/pubkey.pem').read())
n = pub.n
e = pub.e
#print n:21702007965967851183912845012669844623756908507890324243024055496763943595946688940552416734878197459043831494232875785620294668737665396025897150541283087580428261036967329585399916163401369611036124501098728512558174430431806459204349427025717455575024289926516646738721697827263582054632714414433009171634156535642801472435174298248730890036345522414464312932752899972440365978028349224554681969090140541620264972373596402565696085035645624229615500129915303416150964709569033763686335344334340374467597281565279826664494938820964323794098815428802817709142950181265208976166531957235913949338642042322944000000001
p = 139457081371053313087662621808811891689477698775602541222732432884929677435971504758581219546068100871560676389156360422970589688848020499752936702307974617390996217688749392344211044595211963580524376876607487048719085184308509979502505202804812382023512342185380439620200563119485952705668730322944000000001
q = 155617827023249833340719354421664777126919280716316528121008762838820577123085292134385394346751341309377546683859340593439660968379640585296350265350950535158375685103003837903550191128377455111656903429282868722284520586387794090131818535032744071918282383650099890243578253423157468632973312000000000000001
d = gmpy2.invert(e,(p-1)*(q-1))
msg = base64.b64decode("eER0JNIcZYx/t+7lnRvv8s8zyMw8dYspZlne0MQUatQNcnDL/wnHtkAoNdCalQkpcbnZeAz4qeMX5GBmsO+BXyAKDueMA4uy3fw2k/dqFSsZFiB7I9M0oEkqUja52IMpkGDJ2eXGj9WHe4mqkniIayS42o4p9b0Qlz754qqRgkuaKzPWkZPKynULAtFXF39zm6dPI/jUA2BEo5WBoPzsCzwRmdr6QmJXTsau5BAQC5qdIkmCNq7+NLY1fjOmSEF/W+mdQvcwYPbe2zezroCiLiPNZnoABfmPbWAcASVU6M0YxvnXsh2YjkyLFf4cJSgroM3Aw4fVz3PPSsAQyCFKBA==")

key = RSA.construct((long(n),long(e),long(d),long(p),long(q)))
'''for i in range(20):
    enc = key.decrypt(msg)
    msg = enc
print(msg)
'''
msg = bytes_to_long(msg)
for i in range(20):
    enc = pow(msg,d,n)
    msg = enc
print(long_to_bytes(msg))

在这里插入图片描述

问题思考

以上代码中的16~19注释部分是其加密算法对应的解密算法,但是我运行出错了

错误提示:NotImplementedError: Use module Crypto.Cipher.PKCS1_OAEP instead

于是乎只能以21~25行所示代码解,如有师傅清楚问题所在,欢迎在评论区留下妙言。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值