2023陕西省省赛-BigDataEnc
题目描述:
If there were no modulo in the world, it would be as daunting as this challenge.
import pickle
from secret import flag
from Crypto.Util.number import *
N = 128
assert flag.startswith(b'flag{') and flag.endswith(b'}')
class BigDataEnc:
def __init__(self, N):
self.a = 1
self.b = 1
self.N = N
def enc(self, flag):
bits = bin(bytes_to_long(flag))[2:]
LEN = len(bits)
assert LEN == 254
for i in range(LEN):
t = getPrime(self.N)
if int(bits[i]):
self.b *= pow(t, 20)
self.a *= pow(t, 23 + i)
else:
self.a *= pow(t, 20)
self.b *= pow(t, 23 + i)
def save(self):
file_a = open('a', 'wb')
file_b = open('b', 'wb')
pickle.dump(str(self.a), file_a)
pickle.dump(str(self.b), file_b)
file_a.close()
file_b.close()
CheckIn = BigDataEnc(N)
CheckIn.enc(flag[5:-1])
CheckIn.save()
解题思路:
观察题目a和b的构造,可以发现a和b都是由相同的128个大素数的幂组成的
$a=t_1^{20}t_2^{20}...t_{128}^{20}*t_{x_1}^{3+x_1}t_{x_2}^{3+x_2}...t_{x_n}^{3+x_n}$
$b=t_1^{20}t_2^{20}...t_{128}^{20}*t_{y_1}^{3+y_1}t_{y_2}^{3+y_2}...t_{y_n}^{3+y_n}$
所以我们可以得知:
${(t_1t_2...t_{128})}^{20}=gcd(a,b)$
从而可以得到$t_1t_2...t_{128}$的值
然后我们用$a \over {t_1^{20}t_2^{20}...t_{128}^{20}}$就可以得到$t_{x_1}^{3+x_1}t_{x_2}^{3+x_2}...t_{x_n}^{3+x_n}$
用$t_{x_1}^{3+x_1}t_{x_2}^{3+x_2}...t_{x_n}^{3+x_n}$和$t_1t_2...t_{128}$求gcd得$t=t_{x_1}t_{x_2}...t_{x_n}$
再逐位枚举求$t^{(i+3)}$
用$t_{x_1}^{3+x_1}t_{x_2}^{3+x_2}...t_{x_n}^{3+x_n}$除以$t^{(i+3)}$得到$temp$
若$gcd(temp,t)$与$t$不同则可确认该位为1,从而更新$t=temp$
否则可确认该位为0
exp:
from Crypto.Util.number import *
from pickle import *
import gmpy2
import sys
sys.set_int_max_str_digits(0)
file_a = open("./2023shanxi/a", 'rb')
file_b = open("./2023shanxi/b", 'rb')
a = int(load(file_a))
b = int(load(file_b))
g20 = gmpy2.gcd(a, b)
g = gmpy2.iroot(g20, 20)[0]
# print(g)
tmp_a = a // g20
big_in_a = gmpy2.gcd(tmp_a, g)
LEN = 254
flag_list = []
for i in range(3, LEN + 3):
temp = pow(big_in_a, i)
temp_a = tmp_a // temp
tt = gmpy2.gcd(temp_a, big_in_a)
if tt != big_in_a:
flag_list.append('1')
big_in_a = tt
else:
flag_list.append('0')
# print(flag_list)
flag = ''.join(flag_list)
flag = int(flag, 2)
print(long_to_bytes(flag))