10-15记

偶然看到交流群里有人问这题会么,就有了这篇

一、题目

#!/usr/bin/env python3
import gmpy2
from Crypto.Util.number import getPrime
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
from base64 import b64encode

flag = open('flag', 'r').read().strip() * 23

def encrypt(p, q, e, msg):
    while True:
        n = p * q
        try:
            phi = (p - 1)*(q - 1)
            pubkey = RSA.construct((int(n), int(e)))
            key = PKCS1_v1_5.new(pubkey)
            enc = b64encode(key.encrypt(msg))
            return enc
        except:
            p = gmpy2.next_prime(p**2 + q**2)
            q = gmpy2.next_prime(2*p*q)
            e = gmpy2.next_prime(e**2)


p = getPrime(128)
q = getPrime(128)
n = p*q
e = getPrime(64)
pubkey = RSA.construct((n, e))
with open('pubkey.pem', 'wb') as f:
    f.write(pubkey.exportKey())
with open('flag.enc', 'wb') as g:
    g.write(encrypt(p, q, e, flag.encode()))

给了加密脚本还有两个附件

二、题解

读代码,保存pubkey.pem文件中的n、e为初始值,p,q为随机128位,可以读n的值去分解得p,q

观察 encrypt 函数,发现存在 try ... except 结构,而且flag.enc 中的数据很大,说明初始的 n 并不能作为最后加密的 n 值(因为RSA加密需要公钥n的长度至少是大于消息的长度的, 否则加密出来的密文会无法解密)

import gmpy2
import binascii
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
from base64 import *


m=b64decode(open('flag.enc','r').read())
pub=RSA.importKey(open('pubkey.pem','r').read())
n=pub.n
e=pub.e
# print(n)
#n = 62078208638445817213739226854534031566665495569130972218813975279479576033261
#sage 分解n得pq
q=184333227921154992916659782580114145999
p=336771668019607304680919844592337860739
i=1
while 1:
    print(i)
    i+=1
    n=q*p
    if n >= int(binascii.b2a_hex(m),16):
        phi=(p-1)*(q-1)
        d=gmpy2.invert(e,phi)
        prikey=RSA.construct((int(n),int(e),int(d)))
        key=PKCS1_v1_5.new(prikey)
        flag=key.decrypt(m,None)
        break
    else:
        p = gmpy2.next_prime(p ** 2 + q ** 2)
        q = gmpy2.next_prime(2 * p * q)
        e = gmpy2.next_prime(e ** 2)
print(flag)
#1
#2
#3
#4
#b'flag{f@cToR__N_bY_!teratlnG!}'

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值