2021绿城杯 Crypto wp
warm up-->仿射密码
from Crypto.Util.number import *
from flag import flag
assert flag[:5]=='flag{'
str1 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
def encode(plain_text, a, b, m):
cipher_text = ''
for i in plain_text:
if i in str1:
addr = str1.find(i)
cipher_text += str1[(a*addr+b) % m]
else:
cipher_text += i
print(cipher_text)
encode(flag,37,23,52)
# cipher_text = 'aoxL{XaaHKP_tHgwpc_hN_ToXnnht}'
EXP
古典仿射密码,一个个加密,直接使用工具即可解密,调整一下参数
脚本
from Crypto.Util.number import *
str1 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
cipher_text = 'aoxL{XaaHKP_tHgwpc_hN_ToXnnht}'
def decode(cipher_text , a, b, m):
plain_text= ''
for i in cipher_text:
if i in str1:
addr = str1.find(i)
for x in range (len(str1)):
if addr == (a*x+b) % m:
plain_text += str1[x]
else:
plain_text += i
print(plain_text)
decode(cipher_text ,37,23,52)
#flag{AffInE_CIpheR_iS_clAssiC}
flaG{AffINE_cIpher_iS_ClAssic}
RSA1-->化解\((2021*m*1001*p)^emodn为p的倍数\)
from Crypto.Util.number import *
import gmpy2
from flag import flag
assert flag[:5]==b'flag{'
m = bytes_to_long(flag)
p = getPrime(1024)
q = getPrime(1024)
n = p * q
print('n =',n)
e = 0x10001
M = 2021 * m * 1001 * p
c = pow(M,e,n)
print('c =',c)
#n = 17365231154926348364478276872558492775911760603002394353723603461898405740234715001820111548600914907617003806652492391686710256274156677887101997175692277729648456087534987616743724646598234466094779540729413583826355145277980479040157075453694250572316638348121571218759769533738721506811175866990851972838466307594226293836934116659685215775643285465895317755892754473332034234495795936183610569571016400535362762699517686781602302045048532131426035260878979892169441059467623523060569285570577199236309888155833013721997933960457784653262076135561769838704166810384309655788983073376941843467117256002645962737847
#c = 6944967108815437735428941286784119403138319713455732155925055928646536962597672941805831312130689338014913452081296400272862710447207265099750401657828165836013122848656839100854719965188680097375491193249127725599660383746827031803066026497989298856420216250206035068180963797454792151191071433645946245914916732637007117085199442894495667455544517483404006536607121480678688000420422281380539368519807162175099763891988648117937777951069899975260190018995834904541447562718307433906592021226666885638877020304005614450763081337082838608414756162253825697420493509914578546951634127502393647068722995363753321912676
\(M^e {mod n}=(2021*m*1001*p)^emodn\)
EXP
加密后的M必定与n含有一个公约数p,p得到了即得到了q
没有搞明白为什么\(p =gcd(n,c)\)
因为
\[\begin{cases}
n=p*q是p的倍数 \\
c=M^cmodn=(2021 * m * 1001 * p)^e+k*p*q\\
所以c也是p的倍数
\end{cases}
\]
from Crypto.Util.number import *
import gmpy2
n = 17365231154926348364478276872558492775911760603002394353723603461898405740234715001820111548600914907617003806652492391686710256274156677887101997175692277729648456087534987616743724646598234466094779540729413583826355145277980479040157075453694250572316638348121571218759769533738721506811175866990851972838466307594226293836934116659685215775643285465895317755892754473332034234495795936183610569571016400535362762699517686781602302045048532131426035260878979892169441059467623523060569285570577199236309888155833013721997933960457784653262076135561769838704166810384309655788983073376941843467117256002645962737847
c = 6944967108815437735428941286784119403138319713455732155925055928646536962597672941805831312130689338014913452081296400272862710447207265099750401657828165836013122848656839100854719965188680097375491193249127725599660383746827031803066026497989298856420216250206035068180963797454792151191071433645946245914916732637007117085199442894495667455544517483404006536607121480678688000420422281380539368519807162175099763891988648117937777951069899975260190018995834904541447562718307433906592021226666885638877020304005614450763081337082838608414756162253825697420493509914578546951634127502393647068722995363753321912676
e = 0x10001
p = gmpy2.gcd(n,c)
q = n // p
phi = (p-1) * (q-1)
d = gmpy2.invert(e,phi)
M = gmpy2.powmod(c,d,n)
m = M//(2021*1001*p)
flag = long_to_bytes(m)
print(flag)
#flag{Math_1s_1nterest1ng_hah}
RSA2-PLUS-->\(多个相邻素数\quad n1 = p*q*p1*q1\) | Z3库
from Crypto.Util.number import *
import gmpy2
from flag import flag
assert flag[:5]==b'flag{'
m1 = bytes_to_long(flag[:20])
p = getPrime(512)
p1 = gmpy2.next_prime(p)
q = getPrime(512)
q1 = gmpy2.next_prime(q)
n1 = p*q*p1*q1
print('n1 =',n1)
e = 0x10001
c1 = pow(m1,e,n1)
print('c1 =',c1)
m2 = bytes_to_long(flag[20:])
p2 = getPrime(1024)
q2 = getPrime(1024)
print('p2+q2 =',p2+q2)
print('p2*q2 =',p2*q2)
n2 = p2*p2*q2*q2*q2
print('n2 =',n2)
c2 = pow(m2,e,n2)
print('c2 =',c2)
#n1 = 6348779979606280884589422188738902470575876294643492831465947360363568026280963989291591157710389629216109615274754718329987990551836115660879103234129921943824061416396264358110216047994331119920503431491509529604742468032906950984256964560405062345280120526771439940278606226153077959057882262745273394986607004406770035459301695806378598890589432538916219821477777021460189140081521779103226953544426441823244765828342973086422949017937701261348963541035128661464068769033772390320426795044617751909787914185985911277628404632533530390761257251552073493697518547350246993679844132297414094727147161169548160586911
#c1 = 6201882078995455673376327652982610102807874783073703018551044780440620679217833227711395689114659144506630609087600915116940111002026241056808189658969089532597757995423694966667948250438579639890580690392400661711864264184444018345499567505424672090632235109624193289954785503512742400960515331371813467034511130432319427185134018830006918682733848618201088649690422818940385123599468595766345668931882249779415788129316594083269412221804774856038796248038700275509397599351533280014908894068141056694660319816046357462684688942519849441237878018480036145051967731081582598773076490918572392784684372694103015244826
#p2+q2 = 274773146761138462708137582309097386437793891793691383033856524303010811294101933454824485010521468914846151819876043508541879637544444256520741418495479393777132830985856522008561088410862815913292288683761657919121930016956916865849261153721097671315883469348972925757078089715102032241818526925988645578778
#p2*q2 = 18514724270030962172566965941723224386374076294232652258701085781018776172843355920566035157331579524980108190739141959926523082142273672741849552475156278397131571360099018592018959785627785130126477982765210498547680367230723634424036009539347854344573537848628061468892166199866227984167843139793429682559241317072979374002912607549039431398267184818771503468116379618249319324788996321340764624593443106354104274472601170229835219638093242557547840060892527576940077162990069687019966946826210112318408269749294366586682732614372434218768720577917368726530200897558912687470088583774711767599580037663378929000217
#n2 = 40588227045595304080360385041082238507044292731344465815296032905633525556943787610712651675460810768762763493579129831271018141591546207557410817432455139315527674932933085299277599173971912445226532235814580879585317211349524406424200622675880992390782025158621241499693400288031658194434641718026910652327933253877313106112861283314274635124734817398465059373562194694957841264834312640926278890386089611103714990646541470577351599526904458342660444968591197606820361364761648205241041444681145820799054413179462285509661124362074093583494932706249461954240408827087015525507173082129412234486228092002841868365895837463699200959915782767657258729794037776401995309244941171415842403617486719492483671490834562579225506831496881542530519595438932482796867853234159664409420977526102480385193101883785161080269573707156626838551506024455480650224305894501968583442346807126920740779780593650871645915149689424292912611578291912721896864772950410266629045542480009266574096080138709683466489568290569363478444349563498507530805502511051165160827192795520182720802422213364247355775222858214648603034743679187470844212529134374975737510982287957316878179964602394749601431823167982157434890459245394370728942790117156485268116758052636794417268680901420193002289035538753620555488506926366624641291881353268617130968991258983002165300186971963661666476600998389048880565199317280428349802824448329898502788492233381873026217202981921654673840142095839603360666049476100561268336225902504932800605464136192275593886736746497955270280541423593
#c2 = 25591090168544821761746024178724660839590948190451329227481168576490717242294520739865602061082558759751196452117720647426598261568572440942370039702932821941366792140173428488344932203576334292648255551171274828821657097667106792872200082579319963310503721435500623146012954474613150848083425126987554594651797477741828655238243550266972216752593788734836373144363217639612492397228808215205862281278774096317615918854403992620720969173788151215489908812749179861803144937169587452008097008940710091361183942268245271154461872102813602754439939747566507116519362821255724179093051041994730856401493996771276172343313045755916751082693149885922105491818225012844519264933137622929024918619477538521533548551789739698933067212305578480416163609137189891797209277557411169643568540392303036719952140554435338851671440952865151077383220305295001632816442144022437763089133141886924265774247290306669825085862351732336395617276100374237159580759999593028756939354840677333467281632435767033150052439262501059299035212928041546259933118564251119588970009016873855478556588250138969938599988198494567241172399453741709840486953189764289118312870580993115636710724139809708256360212728127786394411676427828431569046279687481368215137561500777480380501551616577832499521295655237360184159889151837766353116185320317774645294201044772828099074917077896631909654671612557207653830344897644115936322128351494551004652981550758791285434809816872381900401440743578104582305215488888563166054568802145921399726673752722820646807494657299104190123945675647
前半段EXP1-->\(多个相邻素数\quad n1 = p*q*p1*q1\)
from Crypto.Util.number import *
from gmpy2 import *
n = 6348779979606280884589422188738902470575876294643492831465947360363568026280963989291591157710389629216109615274754718329987990551836115660879103234129921943824061416396264358110216047994331119920503431491509529604742468032906950984256964560405062345280120526771439940278606226153077959057882262745273394986607004406770035459301695806378598890589432538916219821477777021460189140081521779103226953544426441823244765828342973086422949017937701261348963541035128661464068769033772390320426795044617751909787914185985911277628404632533530390761257251552073493697518547350246993679844132297414094727147161169548160586911
c = 6201882078995455673376327652982610102807874783073703018551044780440620679217833227711395689114659144506630609087600915116940111002026241056808189658969089532597757995423694966667948250438579639890580690392400661711864264184444018345499567505424672090632235109624193289954785503512742400960515331371813467034511130432319427185134018830006918682733848618201088649690422818940385123599468595766345668931882249779415788129316594083269412221804774856038796248038700275509397599351533280014908894068141056694660319816046357462684688942519849441237878018480036145051967731081582598773076490918572392784684372694103015244826
e = 0x10001
def fermat_factorization(n):
factor_list = []
get_context().precision = 2048
sqrt_n = int(sqrt(n))
c = sqrt_n
while True:
c += 1
d_square = c**2 - n
if is_square(d_square):
d_square = mpz(d_square)
get_context().precision = 2048
d = int(sqrt(d_square))
factor_list.append([c+d,c-d])
if len(factor_list)==2:
break
return factor_list
factor_list = fermat_factorization(n)
[X1,Y1] = factor_list[0]
[X2,Y2] = factor_list[1]
assert X1*Y1 == n
assert X2*Y2 == n
p1 = gcd(X1,X2)
q1 = X1 // p1
p2 = gcd(Y1,Y2)
q2 = Y1 // p2
Fai = (p1-1)*(q1-1)*(p2-1)*(q2-1)
d = invert(e,Fai)
print long_to_bytes(pow(c,d,n))
前半段EXP2
两次费马分解即可, 四舍五入, 去年“祥云杯”原题
import time # 导入计时模块
from Crypto.Util.number import *
import gmpy2
n = 6348779979606280884589422188738902470575876294643492831465947360363568026280963989291591157710389629216109615274754718329987990551836115660879103234129921943824061416396264358110216047994331119920503431491509529604742468032906950984256964560405062345280120526771439940278606226153077959057882262745273394986607004406770035459301695806378598890589432538916219821477777021460189140081521779103226953544426441823244765828342973086422949017937701261348963541035128661464068769033772390320426795044617751909787914185985911277628404632533530390761257251552073493697518547350246993679844132297414094727147161169548160586911
c = 6201882078995455673376327652982610102807874783073703018551044780440620679217833227711395689114659144506630609087600915116940111002026241056808189658969089532597757995423694966667948250438579639890580690392400661711864264184444018345499567505424672090632235109624193289954785503512742400960515331371813467034511130432319427185134018830006918682733848618201088649690422818940385123599468595766345668931882249779415788129316594083269412221804774856038796248038700275509397599351533280014908894068141056694660319816046357462684688942519849441237878018480036145051967731081582598773076490918572392784684372694103015244826
e = 0x10001
p1 = q1 = 0
def isqrt(n):
x = n
y = (x + n // x) // 2
while y < x:
x = y
y = (x + n // x) // 2
return x
def fermat(n):
t0 = isqrt(n) + 1
counter = 0
t = t0 + counter
temp = isqrt((t * t) - n)
while True:
counter += 1
t = t0 + counter
temp = isqrt((t * t) - n)
s = temp
p = t + s
q = t - s
if (temp * temp) == ((t * t) - n) and p != p1 and q != q1:
return p, q
# 记录总程序开始时间
start_total = time.time()
# 第一次分解计时
print("开始第一次分解...")
t1_start = time.time()
p1, q1 = fermat(n)
t1_end = time.time()
t1_cost = t1_end - t1_start # 第一次分解耗时(秒)
print(f"found 1(耗时:{t1_cost:.2f}秒)")
# 第二次分解计时
print("开始第二次分解...")
t2_start = time.time()
p2, q2 = fermat(n)
t2_end = time.time()
t2_cost = t2_end - t2_start # 第二次分解耗时(秒)
print(f"found 2(耗时:{t2_cost:.2f}秒)")
# 后续处理(提取素数、计算phi、d、解密)计时
print("开始后续处理...")
t3_start = time.time()
# 注意:原代码用list作为变量名,这里改为factors_list避免与内置类型冲突
factors_list = [p1, q1, p2, q2]
primes = []
assert p1 * q1 == n
assert p2 * q2 == n
for i in factors_list:
for j in factors_list:
if i != j:
tmp = int(gmpy2.gcd(i, j))
if tmp != 1 and tmp not in primes:
primes.append(tmp)
phi = 1
new_n = 1 # 原代码用n覆盖,这里改为new_n避免混淆
for i in primes:
phi *= i - 1
new_n *= i
d = gmpy2.invert(e, phi)
m = gmpy2.powmod(c, d, new_n)
t3_end = time.time()
t3_cost = t3_end - t3_start # 后续处理耗时(秒)
# 总耗时计算
total_cost = time.time() - start_total
# 输出结果和各阶段耗时
print(f"解密结果:{long_to_bytes(m)}")
print(f"\n各阶段耗时:")
print(f"1. 第一次Fermat分解:{t1_cost:.2f}秒")
print(f"2. 第二次Fermat分解:{t2_cost:.2f}秒")
print(f"3. 后续处理(提取素数、计算phi/d、解密):{t3_cost:.2f}秒")
print(f"总运行时间:{total_cost:.2f}秒(约{total_cost/60:.2f}分钟)")
已运行时间:00:00
开始第一次分解...
已运行时间:00:05
found 1
开始第二次分解...
已运行时间:01:49
found 2
解密结果:b'flag{Euler_funct1ons'
总运行时间:110.60秒(约1.84分钟)
后半段EXP1-->Z3库解方程
Z3求解库可以解决这种方程题
import gmpy2
from Crypto.Util.number import long_to_bytes
from z3 import *
# 给定的临时值
tmp1 = 274773146761138462708137582309097386437793891793691383033856524303010811294101933454824485010521468914846151819876043508541879637544444256520741418495479393777132830985856522008561088410862815913292288683761657919121930016956916865849261153721097671315883469348972925757078089715102032241818526925988645578778
tmp2 = 18514724270030962172566965941723224386374076294232652258701085781018776172843355920566035157331579524980108190739141959926523082142273672741849552475156278397131571360099018592018959785627785130126477982765210498547680367230723634424036009539347854344573537848628061468892166199866227984167843139793429682559241317072979374002912607549039431398267184818771503468116379618249319324788996321340764624593443106354104274472601170229835219638093242557547840060892527576940077162990069687019966946826210112318408269749294366586682732614372434218768720577917368726530200897558912687470088583774711767599580037663378929000217
# 使用Z3求解p和q
s = Solver()
p, q = Ints('p q')
s.add(p + q == tmp1)
s.add(p * q == tmp2)
assert s.check() == sat
p = s.model()[p].as_long()
q = s.model()[q].as_long()
# 验证p和q是素数
assert gmpy2.is_prime(p)
assert gmpy2.is_prime(q)
# 计算n和e
n = p * q # 原代码中n的计算方式有误,应该是p*q而不是p*q*q*p*q
e = 65537
# 计算欧拉函数值
phi = (p - 1) * (q - 1)
# 计算私钥d
d = gmpy2.invert(e, phi)
# 给定的密文
c = 25591090168544821761746024178724660839590948190451329227481168576490717242294520739865602061082558759751196452117720647426598261568572440942370039702932821941366792140173428488344932203576334292648255551171274828821657097667106792872200082579319963310503721435500623146012954474613150848083425126987554594651797477741828655238243550266972216752593788734836373144363217639612492397228808215205862281278774096317615918854403992620720969173788151215489908812749179861803144937169587452008097008940710091361183942268245271154461872102813602754439939747566507116519362821255724179093051041994730856401493996771276172343313045755916751082693149885922105491818225012844519264933137622929024918619477538521533548551789739698933067212305578480416163609137189891797209277557411169643568540392303036719952140554435338851671440952865151077383220305295001632816442144022437763089133141886924265774247290306669825085862351732336395617276100374237159580759999593028756939354840677333467281632435767033150052439262501059299035212928041546259933118564251119588970009016873855478556588250138969938599988198494567241172399453741709840486953189764289118312870580993115636710724139809708256360212728127786394411676427828431569046279687481368215137561500777480380501551616577832499521295655237360184159889151837766353116185320317774645294201044772828099074917077896631909654671612557207653830344897644115936322128351494551004652981550758791285434809816872381900401440743578104582305215488888563166054568802145921399726673752722820646807494657299104190123945675647
# 验证n的值(原代码中n2的计算方式与n不同,这里保持与n一致)
n_expected = 40588227045595304080360385041082238507044292731344465815296032905633525556943787610712651675460810768762763493579129831271018141591546207557410817432455139315527674932933085299277599173971912445226532235814580879585317211349524406424200622675880992390782025158621241499693400288031658194434641718026910652327933253877313106112861283314274635124734817398465059373562194694957841264834312640926278890386089611103714990646541470577351599526904458342660444968591197606820361364761648205241041444681145820799054413179462285509661124362074093583494932706249461954240408827087015525507173082129412234486228092002841868365895837463699200959915782767657258729794037776401995309244941171415842403617486719492483671490834562579225506831496881542530519595438932482796867853234159664409420977526102480385193101883785161080269573707156626838551506024455480650224305894501968583442346807126920740779780593650871645915149689424292912611578291912721896864772950410266629045542480009266574096080138709683466489568290569363478444349563498507530805502511051165160827192795520182720802422213364247355775222858214648603034743679187470844212529134374975737510982287957316878179964602394749601431823167982157434890459245394370728942790117156485268116758052636794417268680901420193002289035538753620555488506926366624641291881353268617130968991258983002165300186971963661666476600998389048880565199317280428349802824448329898502788492233381873026217202981921654673840142095839603360666049476100561268336225902504932800605464136192275593886736746497955270280541423593
# 解密密文
m = gmpy2.powmod(c, d, n)
print(long_to_bytes(m))
b'_1s_very_interst1ng}'