Secret Blueprints 2
Задание
В процессе исследования пустоши были найдены новые чертежи. Они похожи на предыдущие, но, кажется, в этот раз данные защищены лучше, или все же нет?
Решение
Для решения задания дан архив, содержащий два файла.
Файл source.py сожержит код, который был использован для шифрования флага:
import random
import os
import math
from Crypto.Util.number import getStrongPrime
def parse_n_parameters_from_file(file_path):
#
# Secret information
#
def flag_to_number(flag):
return int.from_bytes(flag.encode('utf-8'), byteorder='big')
def encrypt_by_public_key(flag):
flag = flag_to_number(flag)
#
# Secret information
#
def main():
flag = os.getenv("CTF_FLAG")
encrypted_flag, n = encrypt_by_public_key(flag)
with open('/app/http/data/data.txt', 'w') as file:
file.write(f"e: {3}\n")
file.write(f"n: {n}\n")
file.write(f"flag: {encrypted_flag}\n")
main()
Файл data.txt содержит данные вида:
e: 3
n: 729174757040172253523548163365790180105209361709917836113773695791537173645448911673257779543603917831880168814616571903180059703041918465096284975303919012033369879858126724540154708473261631395527829506091617084411411005754395467251041858298316019868386083835160290028260408550568787162207173074873203720776161206294391980851854208450368517903886253691764261792956089442981355120178178865263514917743801822928703749282742848104144449978980748583977852090696499986587052000157417577621827068494304201744167296702227994061056789063322097343147666776243701184240957871732345952556444633377034915714528120761252271554421502520930493883941229132496132499509077155317833405135132522109076984513299615384637838586831937446262775982400700005562319150770737553041516941956706734770303774303838288601645024441696843526329512279059656442391542914320563791533453979185048494656728812021253833210175353305384051067649973358457252040824507975971956569048004806796493116922682921515708837865481328655772358455376871461687421353970677105107018470213275984416184077179512172970334612571485302982112440736335585098959350785942203444115433784502673977228892139748216641122377140677166971994959496329973698734112087353061564844811335693993051001431387
flag: 410815861252838831918185733230727124592662045196246756397662046386628909333868652953773049628495691120478988944672330277552406403000914861875971171942977386357921716113731779686142286137514672407861580433915215907250773723946673776607348711383614736360395743321688673707030933130649106303047054840161216256102820685595379501012778742311222515924108655132458817278520714625000
Из анализа содержимого файлов, предложенных для выполнения задания, а также из повтора названия задания, необходимо было сделать вывод о том, что для шифрования флага был использован RSA.
Однако в этот раз для шифрования флага применялся открытый ключ:
encrypted_flag, n = encrypt_by_public_key(flag)
Сразу отметим маленькое значение параметра e=3. Так как шифротекст в RSA получается путем возведения в степень e по модулю n, то, если исходное сообщение в степени e будет меньше n, полученный шифротекст останется равным исходному сообщению в степени e. В таком случае можно получить исходное сообщение просто взяв корень степени e из шифротекста. В данном случае искомый флаг будет равен корню третьей степени из зашифрованного значения.
Более подробно про это можно прочитать здесь.
Ниже приведен код для решения данного задания:
import gmpy2
from Crypto.Util.number import getStrongPrime
def number_flag_to_string(number_flag):
byte_length = (number_flag.bit_length() + 7) // 8
byte_data = number_flag.to_bytes(byte_length, byteorder='big')
return byte_data.decode('utf-8')
def parse_parameters_from_file(file_path):
params = {}
with open(file_path, 'r') as file:
for line in file:
line = line.strip()
if line:
key, value = line.split(": ")
params[key] = int(value)
return params
def main():
data = parse_parameters_from_file("data.txt")
encrypted_flag = data["flag"]
number_flag = gmpy2.iroot(encrypted_flag, 3)[0]
flag = number_flag_to_string(number_flag)
print(flag)
main()
Найденный флаг для приведенных исходных данных:
ptech2024{17d2c5ab414a641c1620623cb5b8cd081f6e749f}