Secret Blueprints

Задание

К нам попали какие-то интересные чертежи, но мы не можем их прочитать. Похоже, что этот шифр не получится взломать, или это только на первый взгляд?

Решение

Для решения задания дан архив, содержащий два файла.

Файл source.py сожержит код, который был использован для шифрования флага:

from Crypto.Util.number import getStrongPrime
import random
import math
import os
  
def generate_params():
    #
    # Secret information
    #
 
def flag_to_number(flag):
    return int.from_bytes(flag.encode('utf-8'), byteorder='big')
 
def encrypt_by_secret_key(flag, d, n):
    flag = flag_to_number(flag)
    #
    # Secret information
    #
 
def main():
    flag = f"ptech2024{{{os.getenv('flag')}}}\n"    
    e, d, n = generate_params()
    encrypted_flag = encrypt_by_secret_key(flag, d, n)
    with open('/app/http/data/data.txt', 'w') as file:
        file.write(f"e: {e}\n")
        file.write(f"n: {n}\n")
        file.write(f"flag: {encrypted_flag}\n")
        
main()

Файл data.txt содержит данные вида:

e: 65537
n: 20430355443713661313451354055202178738260971383301184400746984678148958309856674540477230415240587058891103087516626464458710454337312764555113703025420537768042468660879393643506986985208592335243647996493805697685009965596821503454463171203101807509992245453203266678249272075270384379288481097996381655031903087871231075922894689219002050747016122397456546229736381567343779392240286895531865372668110014155575893878486852043611833594805282160782312330681444254319053635220062243100033718716151463252525029132325715064494226067768948427748131094879500063375056435556635679076110318908974962659227466432018569219117
flag: 6272130892402421507276036649384695812946185081933669563512501252639314704905532499159534342130357752397669501140132483606874663866852606600555611377503693816416829594999231066671828741339034337493720284706559963957157011561250125977035326308602486799605284415342963203544377180809553983569430162527066070214387817287351365012606615214758686786532635499099348646641486340463167747288527261921884896321856467046474113568418693762978532362457544118585086807796277909424800570774207919070034336134644398739514790009995054286677539192541868101503018062810937925260148257996031064506186014407319772281693722860896706194372

Проанализировав содержимое обоих файлов, необходимо было прийти к выводу о том, что шифрования флага был использован RSA. Разберем подробнее работу кода:

  • Флаг передается через переменную окружения
  • Далее происходит генерация параметров e, d и n для RSA
  • Производится шифрование флага с помощью ЗАКРЫТОГО ключа
  • Зашифрованный ключ записывается в файл data.txt вместе с параметрами e и n

Вспоминаем, что RSA является алгоритмом асимметричного шифрования. Так как флаг был зашифрован с помощью закрытого ключа, то для его расшифровки нужен открытый ключ. Открытым ключом для RSA являются параметры e и n, которые уже даны в файле data.txt!. Соответсвенно, необходимо просто произвести расшифровку флага, используя исходные данные.

Ниже приведен код для решения данного задания:

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 decrypt_by_open_key(encrypted_flag, e, n):
    number_flag = pow(encrypted_flag, e, n)
    flag = number_flag_to_string(number_flag)
    return flag
 
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")
    flag = decrypt_by_open_key(data["flag"], data["e"], data["n"])
    print(flag)
 
main()

Найденный флаг для приведенных исходных данных:

ptech2024{f02d883960c76d4bd3b9f591d3dcce564fb6b072}