网信柏鹭杯复现
1.这也是RSA密码算法吗?
crypt01.7z
解压压缩包中没有加密的文件,得到一串morse,解码一下得到压缩包解压密码
得到一个rsa加密
#python3
import sys
sys.path.append("..")
from Crypto.Util.number import *
from random import *
from sage.all import *
from secret import flag1 as flag
num1 = 3
num2 = 5
while(num1<num2):
num1 = getPrime(512)
num2 = getPrime(512)
pt = bytes_to_long(flag) + num2
ring = RealField(1100)
num3 = ring(num1) / ring(num2)
print("num3 = ", num3)
while True:
p = randint(2**511, num1)
q = randint(2**511, num2)
if isPrime(p) and isPrime(q) and p!=q:
break
N = p*q
e = 65537
leak = pow(p-q, num1, num1*num2)
ct = pow(pt, e, N)
print("ct = ", ct)
print("N = ", N)
print("leak = ", leak)
"""
num3 = 1.23389923415003373900567515471436168841941584796842188964423737295914869304653496800649965063081353720701415762591488370228399019899893688681309320356016722276295236528757306976510687729729934668311830828756908988350841843676900575414367123810470585198055372776278588638204471298838884740198056387082949710435502826460830711429956
ct = 31011170589632318837149853165664224847925206003567781692767655474759523146503572164952138829336342836023903919700264739071138739105931471740973631326608186969523753119546323993892359278563753903149741128282349467136720827132122619177620866305659196267641453819504766216964516467658995724859657544518337771393
N = 61860727516406742636690805639158184396057779906729165734489212939937929906456706343476469874085504076991779041906401043694401076841639925611957258119417559980829238154105119701407722069260962772947894516879731956778127512764229384957918619863998939985369399189275568362193066167855420897196095587732512368673
leak = 23213363443983005040318061737977092634638640953366787443691593387275645092922646169818923792205696350020369122807136306157118385984272980615310163206933078119776935167207473544453080959202803743994251355133953187110546017667004996272367137522351606700447920805532616096125523674597551449412004735397779511371
"""
连分数展开num3,得到num1,num2
$$leak=(p-q)^{data_1} mod (data_1*data_2)$$
因为$data_1$为质数,由费马定理得
$$(p-q)^{data_1}mod\ data_1 \equiv p-q$$
由p-q和pq算出$\phi(N)$
接着就是正常rsa
exp:
sage部分:
from Crypto.Util.number import *
from gmpy2 import *
task = 1.23389923415003373900567515471436168841941584796842188964423737295914869304653496800649965063081353720701415762591488370228399019899893688681309320356016722276295236528757306976510687729729934668311830828756908988350841843676900575414367123810470585198055372776278588638204471298838884740198056387082949710435502826460830711429956
data1_data2 = continued_fraction(task)
d_list = data1_data2.convergents()
data1 = 1
data2 = 1
for i in d_list:
data = str(i).split('/')
if len(data)>1 and is_prime(int(data[0])) and is_prime(int(data[1])) and int(data[0]).bit_length() == 512 and int(data[1]).bit_length() == 512:
data1 = data[0]
data2 = data[1]
break
# leak = 1788304673303043190942544050868817075702755835824147546758319150900404422381464556691646064734057970741082481134856415792519944511689269134494804602878628
print(data1)
print(data2)
python部分:
from Crypto.Util.number import *
from gmpy2 import *
data1 = 11167377337790397338811417806698264734026040696284907854286100186126887838302430726803014418419121360514985339992064951270502853852777225947659429837569693
data2 = 9050477566333038464101590216458863799039754468566791821195736389139213194857548339787600682491327798736538059818887575696704421576721592454156775006222517
c = 31011170589632318837149853165664224847925206003567781692767655474759523146503572164952138829336342836023903919700264739071138739105931471740973631326608186969523753119546323993892359278563753903149741128282349467136720827132122619177620866305659196267641453819504766216964516467658995724859657544518337771393
n = 61860727516406742636690805639158184396057779906729165734489212939937929906456706343476469874085504076991779041906401043694401076841639925611957258119417559980829238154105119701407722069260962772947894516879731956778127512764229384957918619863998939985369399189275568362193066167855420897196095587732512368673
leak = 23213363443983005040318061737977092634638640953366787443691593387275645092922646169818923792205696350020369122807136306157118385984272980615310163206933078119776935167207473544453080959202803743994251355133953187110546017667004996272367137522351606700447920805532616096125523674597551449412004735397779511371
p_q = leak % data1
e = 65537
phi = n + 1 - isqrt(p_q ** 2 + 4 * n )
d = invert(e, phi)
print(d)
m = pow(c, d, n)
print(long_to_bytes(m -data2))
2.来一道综合编码题目!
crypt02.7z
里面给了个提示,给了部分压缩包密钥明文已经sha1加密后的值,我们可以爆破一下压缩包密钥:
from string import *
from hashlib import *
c_ascii = 'i?Bgt?_Ld?s?6c9'
c_sha1 = '8c36e4?c1d294?df5bb7a9b?b8bd2d2?f22c1f?9'
sh = sha1()
k = []
# print(ascii_letters)
for i in range(256) :
print(i)
for j in range(256):
for k in range(256):
for x in range(256):
c_ascii = 'i'+ chr(i) + 'Bgt' + chr(j) + '_Ld' + chr(k) + 's' + chr(x) + '6c9'
z = sha1(c_ascii.encode()).hexdigest()
if '8c36e4' in z and 'c1d294' in z:
print(z)
print(c_ascii)
# print(c_ascii)
print('over')
得到密钥:i~BgtN_Ld@sw6c9
打开后发现里头还有层压缩包和flag的加密算法,提示是弱密码,弱密码爆破一下,得到密码:ROT47
得到flag加密后的密文,但好像和flag加密后的密文不像,根据压缩包密码提示,可以猜到是还有一层ROT47
ROT47解密后,得到flag加密的密文:6JnsNxHKJ8mkvhS{rMO_c9apMfHDHObq80PMu{_ww_r{rq
flag的加密算法:
# -*- coding: utf-8 -*-
# python2
import sys
sys.path.append("..")
from secret import key,flag2 as flag
def _l(idx, s):
return s[idx:] + s[:idx]
def mainProc(p, k1, k2):
s = b"abcd07efghij89klmnopqr16stuvwxyz-_{}ABCDEFGHIJKL34MNOPQRST25VWXYZ"
t = [[_l((i+j)%len(s), s) for j in range(len(s))] for i in range(len(s))]
i1 = 0
i2 = 0
c = b""
for a in p:
c += t[s.find(a)][s.find(k1[i1])][s.find(k2[i2])]
i1 = (i1 + 1) % len(k1)
i2 = (i2 + 1) % len(k2)
return c
res = mainProc(flag,key,key[::-1])
print(res)
看起来就是一个变种的维吉尼亚密码,用flag中第i位和key中i%len位和len - i%len位在t表中确定密文
但仔细想想会发现这条加密语句:
c += ts.find(a))][s.find(k2[i2])]
他三层的作用是相同的,都只是右移相应的位数。
比如说字符f,在s表中下标为7,假设k1[i1]为a,k2[i2]为b,下标分别是0、1,那加密过程相当于就是在s中找下标为7+0+1的字符作为密文。(因为是循环右移,要记得模上s表的长度)
所以加密的过程其实是等价于下式:
c += s[(s.find(a) + s.find(k1[i1]) + s.find(k2[i2])) % 65]
那我们其实可以把两位用来加密的密钥当作一个整体key,就相当是一个在s表上变化的一个加密。
我们有flag的头十位:flag{ISEC-
用flag头十位在s表中的位置减去密文头十位在s表中的位置,就可以得到解密密钥带来的偏移值
因为加密过程中的两位加密密钥是头尾照应相加的,所以偏移值对于flag的影响也是对称的(也就是说如果key为5位,那么key第一位和第五位应该是相同的,key应该是对称排布的)
而实际上相减之后得到的解密密钥key'是:
[49, 35, 48, 49, 48, 15, 13, 59, 58, 20]
并没有对称排布,所以我们可以猜测密钥至少有19位以上,假设他有19位则应该是:
[24, 17, 24, 24, 24, 7, 6, 29, 29, 10, 10, 29, 30, 7, 8, 24, 25, 24, 18, 25]
拿去解密,发现并没有出现flag,试到20位,发现可以得到flag
exp:
from Crypto.Util.number import *
from gmpy2 import *
def _l(idx, s):
return s[idx:] + s[:idx]
s = "abcd07efghij89klmnopqr16stuvwxyz-_{}ABCDEFGHIJKL34MNOPQRST25VWXYZ"
print(len(s))
t = [[_l((i+j)%len(s), s) for j in range(len(s))] for i in range(len(s))]
def mainProc(p, k1):
i1 = 0
i2 = 0
c = ""
for a in p:
c += s[(s.find(a) + s.find(k1[i1])) % 65]
i1 = (i1 + 1) % len(k1)
# i2 = (i2 + 1) % len(k2)
return c
flag = 'flag{ISEC-'
code = '6JnsNxHKJ8'
key_list = []
real_key = []
for i in range(len(flag)):
key_list.append((s.find(flag[i]) - s.find(code[i])+ 65) % 65)
real_key.append(((s.find(flag[i]) - s.find(code[i])+ 65) % 65))
print(key_list)
for i in range(len(key_list)):
real_key.append(key_list[len(key_list) - i - 1])
key = []
print(real_key)
for i in real_key:
key.append(s[i])
print(key)
flag = '6JnsNxHKJ8mkvhS{rMO_c9apMfHDHObq80PMu{_ww_r{rq'
res = mainProc(flag,key)
print(res)
但如果20位仍没有出flag,我们可以考虑多爆破几位