第一题:
题目:
himt: 爆破、仿射加密变形
from secret import flag
assert flag.startswith(b'flag{') and flag.endswith(b'}')
table = "!\"#$%&'()*+,-.:<=>?@[\]^_{}ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz"
def Enc(m: bytes) -> bytes:
m = m.decode()
cipher = ''
for i in m:
x = table.index(i)
x = pow(x, -1, len(table))
Index = (20 * x + 24) % len(table)
cipher += table[Index]
return cipher.encode()
m = flag[5:-1]
c = Enc(m.swapcase())
print(c) # b'u-*a058*way08w8M*nwJ51q0sw-?vv8yu**8'
解法一(正向爆破):
table = "!\"#$%&'()*+,-.:<=>?@[\]^_{}ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz"
c = b'u-*a058*way08w8M*nwJ51q0sw-?vv8yu**8'
c = c.decode()
cm_dict = {}
for i in range(1, len(table)):
x = i
x = pow(x, -1, len(table))
Index = (20 * x + 24) % len(table)
cm_dict[Index] = i
flag = ''
for ci in c:
ci = table.index(ci)
Index = cm_dict[ci]
m = table[Index]
flag += m
flag = f"flag{{{flag.swapcase()}}}"
print(flag)
解法二(数论解密):
table = "!\"#$%&'()*+,-.:<=>?@[\]^_{}ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz"
cipher = ''
name = b'u-*a058*way08w8M*nwJ51q0sw-?vv8yu**8'
for i in name:
Index = table.index(chr(i))
x = 20 * pow((Index-24),-1,89)
cipher += table[x % len(table)]
print(cipher.swapcase())
- 数论详细说明如下:
第二题:
题目(第三届粤海杯-决赛Crypto1):
from Crypto.Util.number import *
from secret import flag
m = bytes_to_long(flag)
e = 65537
p = getPrime(1024)#生成一个1024二进制位的素数
q = getPrime(1024)
n = p * q
m = m * 2024 * q
c = pow(m, e, n)
print('c =', c)
print('n =', n)
#c = 11545622607408935458241292536059990101167349630718109609294965462438709273782489441876212917886133281927174501984195623922748845334472739773510801470970817720781268388230179515316476418724726975224719347630031080136490291075031534070900765922279400252680537756834228968929053004372347793194650613987769765467274552851439489471383254054865141037525723254945136184257590195301295660928232207262269582068083178544307777339982522032814759798399706632838087407405751960220739155606798371470343902512348951743472905649502921293269075476246772249983778876956091712601912931337782047911042303929198516654456415853368630203339
#n = 16685436900538999627958075836984455711275215227654508118866426820576750648214363814042620418604845678203948296168102845978815414728545576069310308602991967303882570151371842717385425660457439491696199859652579599985098514579849352058139823030426869537044169471423155839169977271312291018942482182102617647133320398924105420264097756185821980304410848122362329683629865399937502419424391684348738913383188330657655742401743281171234628370950482823006140502343675646036865574770126732307009918543130249736003273056079941336418478673038446442067464892523213081977061437393902307236265097311007382158394034241317995279579
exp:
因为m的因子有q,所以找到c和n的最大公约数即为q。从n再解出p。
from Crypto.Util.number import *
import gmpy2
import libnum
c = 11545622607408935458241292536059990101167349630718109609294965462438709273782489441876212917886133281927174501984195623922748845334472739773510801470970817720781268388230179515316476418724726975224719347630031080136490291075031534070900765922279400252680537756834228968929053004372347793194650613987769765467274552851439489471383254054865141037525723254945136184257590195301295660928232207262269582068083178544307777339982522032814759798399706632838087407405751960220739155606798371470343902512348951743472905649502921293269075476246772249983778876956091712601912931337782047911042303929198516654456415853368630203339
n = 16685436900538999627958075836984455711275215227654508118866426820576750648214363814042620418604845678203948296168102845978815414728545576069310308602991967303882570151371842717385425660457439491696199859652579599985098514579849352058139823030426869537044169471423155839169977271312291018942482182102617647133320398924105420264097756185821980304410848122362329683629865399937502419424391684348738913383188330657655742401743281171234628370950482823006140502343675646036865574770126732307009918543130249736003273056079941336418478673038446442067464892523213081977061437393902307236265097311007382158394034241317995279579
q = math.gcd(c,n)
p = n // q
e = 65537
print(p)
# n = p * q
phi = (p - 1) * (q - 1)
print(phi)
d = gmpy2.invert(e,phi)
m = pow(c,d,n)
m = m // (2024*q)
print(long_to_bytes(m))#这里记得转换一下
第三题:
题目(第三届粤海杯-决赛Crypto2):
from hashlib import md5
from secret import hint
from Crypto.Util.strxor import strxor
hint1 = hint[:6] #前六位
hint2 = hint[6:] #从第气位开始
assert hint1.islower() #判断是一个小写字母
print(md5(hint1).hexdigest())
print(strxor(hint1, hint2).decode())
"""
b5dd60e56f64aa1d259ab21c3973205f
TCUI_B
"""
exp:
import string
from tqdm import *
from hashlib import md5
from itertools import product
from Crypto.Util.strxor import strxor
hint1_c= "b5dd60e56f64aa1d259ab21c3973205f"
hint1_xor_hint2 = 'TCUI_B'
table = string.ascii_lowercase
for hint1 in tqdm(product(table, repeat=6)):
hint1 = ''.join(hint1).encode()
if md5(hint1).hexdigest() == hint1_c:
hint2 = strxor(hint1, hint1_xor_hint2.encode())
hint = hint1+hint2
print(hint) # tryxor 1,100
break
import base64
cipher = b"Bu`pB+kaVr]oV\NqBK(*B\IbTL|pUuQlU*QoBr^uTLZpU*I*VLU-VLB!"
for t in range(1,101):
c = ""
for i in cipher:
c += chr(i ^ t)
try:
msg = base64.b64decode(c)
if b"flag" in msg:
print(msg) # flag{261045be-6d43-7a2b-3b0f1f-0a3d653956}
break
except:
continue
第四题:
题目:给出n, c1, c2, e1*e2
n = 23723414709663043409146354803167768676484239031400646854344921581190842455020298542679503185959169237351051283957808491272176607589972102017725217000980459409011765777305036376238334392654701713028578404550441412521528096494483705166107924141060306111730935285286442299028811733353145813755051318853095870353494707151967367912118298118285822794149957221321943818652577443815883589657620731416673718056733736043424734846424920674873434253469199349509358967749850577159394268891674156450757240830233448999712357318363199170045863588924264511829817509100474166090712813299549787004962346680319872798058231188915628383591
c1 = 19054912774147628727553917598318536324166149639543661440938862373325472740612249436160410830877486186040052106255634085434218097705885466041251507988011368642912696888436661688751400979996939440386005462275597837891144799805829564596722747856176178371417553527156064062175120040399642658034642303212443343190336774432678439552199370842494606152369382835846688899438806677242794145486160825601378269966409132805334341258559358175137602547810978801876853296509228350723466401954436323165165393596214066597752251797884080416877041663915509051711571979131521014273115893792023266190735124851850698647470042538070138972920
c2 = 4490538789057573761504993536020749252128430743130655544771616036039597648387562955542457059064263092943953642271064630845544109444089794366487650060454509019455549834788373801758638846202744776342542046709631245793895398748825742566870869785973680707337905651332408048050432199901437246930344414459178264677544957506430818815995656423679626408760273187218494529527907212920442401843942300205444207127386748755283120742011676190160487038975352496744040261653217263840760717217725774971768938832680363884456641540497915440248468759706550639924866379591404304501009876129733453810653383380691467000199986316814509832670
e = e1*e2
e = 104481
解法一:(这种做法有点不稳,有些题目做不出?)
题目给了两个c、两个e和n,推测为共模攻击,但e1和e2给的是乘积,根据共模攻击的要求,e1和e2互质,且需要是整除,可通过脚本爆破:
from gmpy2 import *
from Crypto.Util.number import *
n=23723414709663043409146354803167768676484239031400646854344921581190842455020298542679503185959169237351051283957808491272176607589972102017725217000980459409011765777305036376238334392654701713028578404550441412521528096494483705166107924141060306111730935285286442299028811733353145813755051318853095870353494707151967367912118298118285822794149957221321943818652577443815883589657620731416673718056733736043424734846424920674873434253469199349509358967749850577159394268891674156450757240830233448999712357318363199170045863588924264511829817509100474166090712813299549787004962346680319872798058231188915628383591
c1=19054912774147628727553917598318536324166149639543661440938862373325472740612249436160410830877486186040052106255634085434218097705885466041251507988011368642912696888436661688751400979996939440386005462275597837891144799805829564596722747856176178371417553527156064062175120040399642658034642303212443343190336774432678439552199370842494606152369382835846688899438806677242794145486160825601378269966409132805334341258559358175137602547810978801876853296509228350723466401954436323165165393596214066597752251797884080416877041663915509051711571979131521014273115893792023266190735124851850698647470042538070138972920
c2=4490538789057573761504993536020749252128430743130655544771616036039597648387562955542457059064263092943953642271064630845544109444089794366487650060454509019455549834788373801758638846202744776342542046709631245793895398748825742566870869785973680707337905651332408048050432199901437246930344414459178264677544957506430818815995656423679626408760273187218494529527907212920442401843942300205444207127386748755283120742011676190160487038975352496744040261653217263840760717217725774971768938832680363884456641540497915440248468759706550639924866379591404304501009876129733453810653383380691467000199986316814509832670
e= 104481
e1e2 = e
for e1 in range(2,e):
e2=e//e1
if( e%e1==0 and gcd(e1, e2)==1):
s = gcdext(e1, e2) # gmpy2.gcdext(),扩展欧几里得算法,返回tuple元组,满足s[1]*e1+s[2]*e2=1
m = pow(c1, s[1], n) * pow(c2, s[2], n) % n # 获取明文m
m = long_to_bytes(m)
if(b"flag" in m):
print(m)
解法二:
参考文章:【密码学RSA】共模攻击原理详解_已知e1*e2的共模攻击题_rsa共模攻击原理-CSDN博客
n = 23723414709663043409146354803167768676484239031400646854344921581190842455020298542679503185959169237351051283957808491272176607589972102017725217000980459409011765777305036376238334392654701713028578404550441412521528096494483705166107924141060306111730935285286442299028811733353145813755051318853095870353494707151967367912118298118285822794149957221321943818652577443815883589657620731416673718056733736043424734846424920674873434253469199349509358967749850577159394268891674156450757240830233448999712357318363199170045863588924264511829817509100474166090712813299549787004962346680319872798058231188915628383591
c1 = 19054912774147628727553917598318536324166149639543661440938862373325472740612249436160410830877486186040052106255634085434218097705885466041251507988011368642912696888436661688751400979996939440386005462275597837891144799805829564596722747856176178371417553527156064062175120040399642658034642303212443343190336774432678439552199370842494606152369382835846688899438806677242794145486160825601378269966409132805334341258559358175137602547810978801876853296509228350723466401954436323165165393596214066597752251797884080416877041663915509051711571979131521014273115893792023266190735124851850698647470042538070138972920
c2 = 4490538789057573761504993536020749252128430743130655544771616036039597648387562955542457059064263092943953642271064630845544109444089794366487650060454509019455549834788373801758638846202744776342542046709631245793895398748825742566870869785973680707337905651332408048050432199901437246930344414459178264677544957506430818815995656423679626408760273187218494529527907212920442401843942300205444207127386748755283120742011676190160487038975352496744040261653217263840760717217725774971768938832680363884456641540497915440248468759706550639924866379591404304501009876129733453810653383380691467000199986316814509832670
e1e2 = 104481
import libnum
import gmpy2
def rsa_gongmo_def(e1,e2,c1,c2,n):
s,s1,s2 = gmpy2.gcdext(e1, e2)
m = (pow(c1,s1,n) * pow(c2 ,s2 ,n)) % n
return int(m)
def de(c, e, n): # 因为此时的m不是真正的m,而是m^k,所以对m^k进行爆破
k = 0
while k < 1000: # 指定k小于1000
mk = c + n * k
flag, true1 = gmpy2.iroot(mk, e) # 返回的第一个数值为开方数,第二个数值为布尔型,可整除为true
if True == true1:
return flag
k += 1
for e1 in range(2, e1e2):
if e1e2 % e1 == 0: # 爆破可整除的e
e2 = e1e2 // e1
c = rsa_gongmo_def(e1, e2, c1, c2, n)
e = gmpy2.gcd(e1, e2)
m1 = de(c, e, n)
if m1: # 指定输出m1
print(libnum.n2s(int(m1)))