天天看點

BUUCTF Crypto [GWCTF 2019]BabyRSA、[BJDCTF2020]easyrsa

一、[GWCTF 2019]BabyRSA

下載下傳題目得到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()

           

再看一下secret檔案

N=636585149594574746909030160182690866222909256464847291783000651837227921337237899651287943597773270944384034858925295744880727101606841413640006527614873110651410155893776548737823152943797884729130149758279127430044739254000426610922834573094957082589539445610828279428814524313491262061930512829074466232633130599104490893572093943832740301809630847541592548921200288222432789208650949937638303429456468889100192613859073752923812454212239908948930178355331390933536771065791817643978763045030833712326162883810638120029378337092938662174119747687899484603628344079493556601422498405360731958162719296160584042671057160241284852522913676264596201906163
m1=90009974341452243216986938028371257528604943208941176518717463554774967878152694586469377765296113165659498726012712288670458884373971419842750929287658640266219686646956929872115782173093979742958745121671928568709468526098715927189829600497283118051641107305128852697032053368115181216069626606165503465125725204875578701237789292966211824002761481815276666236869005129138862782476859103086726091860497614883282949955023222414333243193268564781621699870412557822404381213804026685831221430728290755597819259339616650158674713248841654338515199405532003173732520457813901170264713085107077001478083341339002069870585378257051150217511755761491021553239
m2=487443985757405173426628188375657117604235507936967522993257972108872283698305238454465723214226871414276788912058186197039821242912736742824080627680971802511206914394672159240206910735850651999316100014691067295708138639363203596244693995562780286637116394738250774129759021080197323724805414668042318806010652814405078769738548913675466181551005527065309515364950610137206393257148357659666687091662749848560225453826362271704292692847596339533229088038820532086109421158575841077601268713175097874083536249006018948789413238783922845633494023608865256071962856581229890043896939025613600564283391329331452199062858930374565991634191495137939574539546
           

其中m1和m2分别是c1、c2加密得到的。

1、分析

1、加密過程:加密算法中首先給出了flag長度是38個字元,再将flag分成左右兩部分;接下來生成了p和q,從腳本中可以看出,q是p的下一個素數,是以兩個數非常接近,我們可以把N開二次方,所得結果的nextprime就是q;再通過兩個關系式得到c1和c2,對c1、c2加密就得到了我們已知的密文m1和m2。

2、解題思路:隻要我們計算出c1、c2的值,就可通過方程組計算出flag的左右兩部分F1、F2

BUUCTF Crypto [GWCTF 2019]BabyRSA、[BJDCTF2020]easyrsa

而求出c1、c2的關鍵就是找到p、q,在加密過程中我們已經分析出了p、q的求法,當然,由于p、q非常接近,也可以使用yafu進行分解。是以此題也就迎刃而解了。

3、sympy庫:sympy是一個Python的科學計算庫,在求解方程組時使用這個庫會友善許多,當然功能還有很多,這裡就不細講了;之前遇到過,這裡留個記錄,友善複習:Python 中的Sympy詳細使用

2、解題腳本

# -*- coding: UTF-8 -*-
from gmpy2 import *
from Crypto.Util.number import *
import sympy
import time

n=mpz(636585149594574746909030160182690866222909256464847291783000651837227921337237899651287943597773270944384034858925295744880727101606841413640006527614873110651410155893776548737823152943797884729130149758279127430044739254000426610922834573094957082589539445610828279428814524313491262061930512829074466232633130599104490893572093943832740301809630847541592548921200288222432789208650949937638303429456468889100192613859073752923812454212239908948930178355331390933536771065791817643978763045030833712326162883810638120029378337092938662174119747687899484603628344079493556601422498405360731958162719296160584042671057160241284852522913676264596201906163)
m1=90009974341452243216986938028371257528604943208941176518717463554774967878152694586469377765296113165659498726012712288670458884373971419842750929287658640266219686646956929872115782173093979742958745121671928568709468526098715927189829600497283118051641107305128852697032053368115181216069626606165503465125725204875578701237789292966211824002761481815276666236869005129138862782476859103086726091860497614883282949955023222414333243193268564781621699870412557822404381213804026685831221430728290755597819259339616650158674713248841654338515199405532003173732520457813901170264713085107077001478083341339002069870585378257051150217511755761491021553239
m2=487443985757405173426628188375657117604235507936967522993257972108872283698305238454465723214226871414276788912058186197039821242912736742824080627680971802511206914394672159240206910735850651999316100014691067295708138639363203596244693995562780286637116394738250774129759021080197323724805414668042318806010652814405078769738548913675466181551005527065309515364950610137206393257148357659666687091662749848560225453826362271704292692847596339533229088038820532086109421158575841077601268713175097874083536249006018948789413238783922845633494023608865256071962856581229890043896939025613600564283391329331452199062858930374565991634191495137939574539546
e = 0x10001

s = time.clock()
q = next_prime(iroot(n,2)[0])
p = n//q
#print 'p=',p,'q=',q
phi = (p-1)*(q-1)
d = invert(e,phi)
c1 = pow(m1,d,n)
c2 = pow(m2,d,n)

F1 = sympy.Symbol('F1')#方程組定義變量
F2 = sympy.Symbol('F2')
f1 = F1+F2-c1
f2 = pow(F1,3)+pow(F2,3)-c2
result = sympy.solve([f1,f2],[F1,F2])

flag1 = long_to_bytes(result[0][1])
flag2 = long_to_bytes(result[0][0])
flag  = flag1 + flag2
print flag
print '[!]Timer:', round(time.clock() - s, 2), 's'
           

解方程組可能需要一定時間,我沒有化簡,跑了兩分多鐘

BUUCTF Crypto [GWCTF 2019]BabyRSA、[BJDCTF2020]easyrsa

二、[BJDCTF2020]easyrsa

題目:

from Crypto.Util.number import getPrime,bytes_to_long
from sympy import Derivative
from fractions import Fraction
from secret import flag

p=getPrime(1024)
q=getPrime(1024)
e=65537
n=p*q
z=Fraction(1,Derivative(arctan(p),p))-Fraction(1,Derivative(arth(q),q))
m=bytes_to_long(flag)
c=pow(m,e,n)
print(c,z,n)
'''
output:
7922547866857761459807491502654216283012776177789511549350672958101810281348402284098310147796549430689253803510994877420135537268549410652654479620858691324110367182025648788407041599943091386227543182157746202947099572389676084392706406084307657000104665696654409155006313203957292885743791715198781974205578654792123191584957665293208390453748369182333152809882312453359706147808198922916762773721726681588977103877454119043744889164529383188077499194932909643918696646876907327364751380953182517883134591810800848971719184808713694342985458103006676013451912221080252735948993692674899399826084848622145815461035
32115748677623209667471622872185275070257924766015020072805267359839059393284316595882933372289732127274076434587519333300142473010344694803885168557548801202495933226215437763329280242113556524498457559562872900811602056944423967403777623306961880757613246328729616643032628964072931272085866928045973799374711846825157781056965164178505232524245809179235607571567174228822561697888645968559343608375331988097157145264357626738141646556353500994924115875748198318036296898604097000938272195903056733565880150540275369239637793975923329598716003350308259321436752579291000355560431542229699759955141152914708362494482
15310745161336895413406690009324766200789179248896951942047235448901612351128459309145825547569298479821101249094161867207686537607047447968708758990950136380924747359052570549594098569970632854351825950729752563502284849263730127586382522703959893392329333760927637353052250274195821469023401443841395096410231843592101426591882573405934188675124326997277775238287928403743324297705151732524641213516306585297722190780088180705070359469719869343939106529204798285957516860774384001892777525916167743272419958572055332232056095979448155082465977781482598371994798871917514767508394730447974770329967681767625495394441

'''

           

1、分析

這道題無非是考數學,重點是了解Derivative()和Fraction()的作用,

Derivative是表示導函數的類,它的第一個參數是需要進行求導的數學函數,第二個參數是求導的自變量,注意:Derivative所得到的是一個導函數,它不會進行求導運算;例:t=Derivative(sin(x),x)

更多請參考:Sympy指南

Fraction()也很簡單,就是進行分數運算,例:Fraction(2,8)等于0.25,

詳細參考:python中進行分數(fraction)運算

再然後就是大一高數學的對arctan(x)和arth(x)求導,忘得差不多了,記錄下

arctan(x)的導數為1/(1+x^2),

arth(x)是反雙曲函數正切,

BUUCTF Crypto [GWCTF 2019]BabyRSA、[BJDCTF2020]easyrsa

由此對加密腳本中的z化簡得到:p^2 + q^2

2、解密腳本

# -*- coding: UTF-8 -*-
from gmpy2 import *
from Crypto.Util.number import *
import sympy
import time

e=65537
c = 7922547866857761459807491502654216283012776177789511549350672958101810281348402284098310147796549430689253803510994877420135537268549410652654479620858691324110367182025648788407041599943091386227543182157746202947099572389676084392706406084307657000104665696654409155006313203957292885743791715198781974205578654792123191584957665293208390453748369182333152809882312453359706147808198922916762773721726681588977103877454119043744889164529383188077499194932909643918696646876907327364751380953182517883134591810800848971719184808713694342985458103006676013451912221080252735948993692674899399826084848622145815461035
z = 32115748677623209667471622872185275070257924766015020072805267359839059393284316595882933372289732127274076434587519333300142473010344694803885168557548801202495933226215437763329280242113556524498457559562872900811602056944423967403777623306961880757613246328729616643032628964072931272085866928045973799374711846825157781056965164178505232524245809179235607571567174228822561697888645968559343608375331988097157145264357626738141646556353500994924115875748198318036296898604097000938272195903056733565880150540275369239637793975923329598716003350308259321436752579291000355560431542229699759955141152914708362494482
n = 15310745161336895413406690009324766200789179248896951942047235448901612351128459309145825547569298479821101249094161867207686537607047447968708758990950136380924747359052570549594098569970632854351825950729752563502284849263730127586382522703959893392329333760927637353052250274195821469023401443841395096410231843592101426591882573405934188675124326997277775238287928403743324297705151732524641213516306585297722190780088180705070359469719869343939106529204798285957516860774384001892777525916167743272419958572055332232056095979448155082465977781482598371994798871917514767508394730447974770329967681767625495394441
s = time.clock()

p = sympy.Symbol('p')#方程組定義變量
q = sympy.Symbol('q')
f1 = p**2+q**2-z
f2 = p*q-n
result = sympy.solve([f1,f2],[p,q])
#print result
p = int(result[2][0])
q = int(result[2][1])

phi = (p-1)*(q-1)
d = invert(e,phi)
m = pow(c,d,p*q)
print long_to_bytes(m)
print '[!]Timer:', round(time.clock() - s, 2)
           

此題主要記錄Derivative()和Fraction()兩個函數的作用

BUUCTF Crypto [GWCTF 2019]BabyRSA、[BJDCTF2020]easyrsa