[GWCTF 2019]BabyRSA 1

问题

首先拿到压缩包,压缩包中给了我们两个文件
在这里插入图片描述
一个是encrypt.py 这个文件是加密脚本
另一个是secret里面有我们所需要的数据

分析加密脚本

打开脚本

import hashlib
import sympy
from Crypto.Util.number import *

flag = 'GWHT{******}'
secret = '******'

assert(len(flag) == 38)

half = len(flag) / 2

flag1 = flag[:half]
flag2 = flag[half:]

secret_num = getPrime(1024) * bytes_to_long(secret)

p = sympy.nextprime(secret_num)
q = sympy.nextprime(p)

N = p * q

e = 0x10001

F1 = bytes_to_long(flag1)
F2 = bytes_to_long(flag2)

c1 = F1 + F2
c2 = pow(F1, 3) + pow(F2, 3)
assert(c2 < N)

m1 = pow(c1, e, N)
m2 = pow(c2, e, N)

output = open('secret', 'w')
output.write('N=' + str(N) + '\n')
output.write('m1=' + str(m1) + '\n')
output.write('m2=' + str(m2) + '\n')
output.close()

然后发现自己没有安装symy和Crypto,于是就去github下载对应的文件然后在安装(在这个过程中我想说的是英语是真的重要,文件的阅读多是英文的,看不懂是真的难受)
通过对代码进行分析可得大致的加密过程为:

  1. 给一个明文flag,和一个字符串secret
  2. 随机生成一个1024位(2进制)的素数并将sercret转换为long类型然后将这两个结果相乘得到secret_num(注: bytes_to_long的过程大概是以字节为进制进行运算,比如"ab",就是28 *ord(a)+ord(b))
  3. 取secret_num的下一个素数作为p,取p的下一个素数作为q,得到N=p*q
  4. f1取明文前一半,f2取明文后一半并将f1,f2转成long类型
  5. 封装f1和f2出c1,c2,并对c1,c2用rsa进一步加密得m1,m2
  6. 给出密文 N,m1,m2

decrypt

  1. 题目给出了N,并且通过分析我们可以知道p和q是两个相邻得素数,所以将N进行开平方运算(iroot(N,2))后可以得到一个值x并且p
  2. 通过preprime和nextprime函数,可以求出p,q
  3. 然后进行RSA解密得出c1和c2
    10.至此,我们 得到两个方程 :
    c1=F1+F2
    c2=F13+F23
    令m=c1,n=c2(主要是c1,c2要写两个字太累,所以换成m,n)
    通过解方程后可得F1=iroot((m/n-n2)/3+ n2/4)+n/2
    F2=c1-F1
    然后进行16进制转换后解码并且做拼接就可得到Flag

解密脚本

import gmpy2
import sympy.crypto.crypto
import Cryptodome.Util.number
from Crypto.Util.number import bytes_to_long
import binascii
N=636585149594574746909030160182690866222909256464847291783000651837227921337237899651287943597773270944384034858925295744880727101606841413640006527614873110651410155893776548737823152943797884729130149758279127430044739254000426610922834573094957082589539445610828279428814524313491262061930512829074466232633130599104490893572093943832740301809630847541592548921200288222432789208650949937638303429456468889100192613859073752923812454212239908948930178355331390933536771065791817643978763045030833712326162883810638120029378337092938662174119747687899484603628344079493556601422498405360731958162719296160584042671057160241284852522913676264596201906163
x=gmpy2.iroot(N,2)[0]
m1=90009974341452243216986938028371257528604943208941176518717463554774967878152694586469377765296113165659498726012712288670458884373971419842750929287658640266219686646956929872115782173093979742958745121671928568709468526098715927189829600497283118051641107305128852697032053368115181216069626606165503465125725204875578701237789292966211824002761481815276666236869005129138862782476859103086726091860497614883282949955023222414333243193268564781621699870412557822404381213804026685831221430728290755597819259339616650158674713248841654338515199405532003173732520457813901170264713085107077001478083341339002069870585378257051150217511755761491021553239
m2=487443985757405173426628188375657117604235507936967522993257972108872283698305238454465723214226871414276788912058186197039821242912736742824080627680971802511206914394672159240206910735850651999316100014691067295708138639363203596244693995562780286637116394738250774129759021080197323724805414668042318806010652814405078769738548913675466181551005527065309515364950610137206393257148357659666687091662749848560225453826362271704292692847596339533229088038820532086109421158575841077601268713175097874083536249006018948789413238783922845633494023608865256071962856581229890043896939025613600564283391329331452199062858930374565991634191495137939574539546

p=sympy.crypto.crypto.nextprime(x)
q=N//p
e=0x10001
d=gmpy2.invert(e,(p-1)*(q-1))
c1=gmpy2.powmod(m1,d,N)
c2=gmpy2.powmod(m2,d,N)
n=c1
m=c2
f1=gmpy2.iroot((((m//n)-n*n)//3)+(n*n)//4,2)[0]+n//2
f2=n-f1
print(binascii.unhexlify(hex(f1)[2:])+binascii.unhexlify(hex(f2)[2:]))

运行后得到Flag
在这里插入图片描述

结束

这道题的解密过程并没有用到secret,我也不是很清楚是否还有其它的解密方法,总的来说,看懂加密脚本是编写解密脚本的关键一步,在遇到不认识的函数时可以去网上查,遇到没遇过的模块可以尝试去下载导入.或许在这些模块中前辈们给我们留下了许多有用的东西.

你可能感兴趣的:(RSA)