def test_decode_unsupported_version(self): password = b"fooobarr" data = b"#bellavita" version = len(crypto.pack_versions).to_bytes(1, "big") pack = crypto.encode(password, data, b"") offset = crypto.PackVersion.hash_len pack = pack[:offset] + version + pack[offset + 1 :] with self.assertRaises(ValueError): crypto.decode(password, pack)
def crypt_file_main(): parser = argparse.ArgumentParser( description='(De)Crypt a file according to a given password') parser.add_argument('-d', '--decrypt', action='store_true') parser.add_argument('-m', '--metadata', help='metadata input file') parser.add_argument('zip_password', help='hexified zip password') parser.add_argument('input_file', help='input file', nargs='?', default='-') parser.add_argument('output_file', help='output file', nargs='?', default='-') args = parser.parse_args() input_file = open(args.input_file, 'rb') if args.input_file != '-' else sys.stdin.buffer metadata_file = open(args.metadata, 'rb') if args.metadata is not None else None output_file = open(args.output_file, 'wb') if args.output_file != '-' else sys.stdout.buffer zip_password = bytes.fromhex(args.zip_password) input_data = input_file.read() if args.decrypt: assert validate(input_data) output_file.write(decode(zip_password, input_data)) else: metadata_in = metadata_file.read( ) if metadata_file is not None else b"" output_file.write(encode(zip_password, input_data, metadata_in))
def test_encode_decode(self): for version in range(len(crypto.pack_versions)): with self.subTest(): password = b"fooobarr" data = b"#bellavita" encrypted = crypto.encode(password, data, b"", version=version) self.assertEqual(data, crypto.decode(password, encrypted))
def crypt_file_main(): parser = argparse.ArgumentParser( description="(De)Crypt a file according to a given password" ) parser.add_argument("-d", "--decrypt", action="store_true") parser.add_argument("-m", "--metadata", help="metadata input file") parser.add_argument("zip_password", help="hexified zip password") parser.add_argument("input_file", help="input file", nargs="?", default="-") parser.add_argument("output_file", help="output file", nargs="?", default="-") args = parser.parse_args() input_file = ( open(args.input_file, "rb") if args.input_file != "-" else sys.stdin.buffer ) metadata_file = open(args.metadata, "rb") if args.metadata is not None else None output_file = ( open(args.output_file, "wb") if args.output_file != "-" else sys.stdout.buffer ) zip_password = bytes.fromhex(args.zip_password) input_data = input_file.read() if args.decrypt: assert validate(input_data) output_file.write(decode(zip_password, input_data)) else: metadata_in = metadata_file.read() if metadata_file is not None else b"" output_file.write(encode(zip_password, input_data, metadata_in))
def build_pack(metadata): asset = os.path.join(os.path.dirname(__file__), "./assets/pack.zip.enc") with open(asset, "rb") as f: zip = crypto.decode(bytes.fromhex(Utils.ZIP_PASSWORD), f.read()) password = bytes.fromhex(Utils.ZIP_PASSWORD) return crypto.encode(password, zip, metadata.encode())
def drop_contest(self, admin_token): """ POST /admin/drop_contest """ if not os.path.exists(Config.encrypted_file): self.raise_exc(NotFound, "NOT_FOUND", "No packs found") Logger.warning("DROP_CONTEST", "Started dropping contest") with open(Config.encrypted_file, "rb") as f: pack = f.read() db_token = Database.get_meta("admin_token") # contest has been extracted but the token is wrong if db_token is not None and db_token != admin_token: self.raise_exc(Forbidden, "FORBIDDEN", "Wrong token") # contest has not been extracted if db_token is None: try: password = crypto.recover_file_password_from_token(admin_token) crypto.decode(password, pack) except nacl.exceptions.CryptoError: # pack password is wrong self.raise_exc(Forbidden, "FORBIDDEN", "Wrong pack token") metadata = ruamel.yaml.safe_load(crypto.metadata(pack).strip(b"\x00")) if not metadata.get("deletable"): self.raise_exc(Forbidden, "FORBIDDEN", "Contest not deletable") shutil.rmtree(Config.storedir, ignore_errors=True) shutil.rmtree(Config.statementdir, ignore_errors=True) shutil.rmtree(Config.contest_path, ignore_errors=True) for f in (Config.encrypted_file, Config.decrypted_file): try: os.remove(f) except FileNotFoundError: pass Database.disconnect_database() for f in glob.glob(Config.db + "*"): os.remove(f) Database.connect_to_database() Logger.warning("DROP_CONTEST", "Contest dropped") return {}
def extract_contest(token): """ Decrypt and extract the contest and store the used admin token in the database """ if "-" not in token: BaseHandler.raise_exc(Forbidden, "WRONG_PASSWORD", "The provided password is malformed") try: username, password = token.split("-", 1) secret, scrambled_password = decode_data(password, SECRET_LEN) file_password = recover_file_password(username, secret, scrambled_password) except ValueError: BaseHandler.raise_exc(Forbidden, "WRONG_PASSWORD", "The provided password is malformed") try: with open(Config.encrypted_file, "rb") as encrypted_file: encrypted_data = encrypted_file.read() decrypted_data = decode(file_password, encrypted_data) with open(Config.decrypted_file, "wb") as decrypted_file: decrypted_file.write(decrypted_data) except FileNotFoundError: BaseHandler.raise_exc(NotFound, "NOT_FOUND", "The contest pack was not uploaded yet") except nacl.exceptions.CryptoError: BaseHandler.raise_exc(Forbidden, "WRONG_PASSWORD", "The provided password is wrong") except OSError as ex: BaseHandler.raise_exc(InternalServerError, "FAILED", str(ex)) zip_abs_path = os.path.realpath(Config.decrypted_file) wd = os.getcwd() try: os.makedirs(Config.contest_path, exist_ok=True) os.chdir(Config.contest_path) with zipfile.ZipFile(zip_abs_path) as f: f.extractall() real_yaml = os.path.join("__users__", username + ".yaml") if not os.path.exists(real_yaml): BaseHandler.raise_exc(Forbidden, "WRONG_PASSWORD", "Invalid username for the given pack") os.symlink(real_yaml, "contest.yaml") Logger.info("CONTEST", "Contest extracted") except zipfile.BadZipFile as ex: BaseHandler.raise_exc(Forbidden, "FAILED", str(ex)) finally: os.chdir(wd) Database.set_meta("admin_token", token)
def main(args): with open(args.pack, "rb") as pack: pack = pack.read() if not validate(pack): raise AssertionError("Corrupted pack") meta = ruamel.yaml.safe_load(metadata(pack).strip(b"\x00")) if meta.get("deletable"): print(Fore.YELLOW, "WARNING: The pack is marked as deletable", Fore.RESET) if not meta.get("name"): print(Fore.YELLOW, "WARNING: The pack metadata does not include 'name'", Fore.RESET) if not meta.get("description"): print(Fore.YELLOW, "WARNING: The pack metadata does not include 'description'", Fore.RESET) decoded = decode(bytes.fromhex(args.password), pack) tasks = args.tasks.split(",") if args.solutions: solutions = [ list(map(os.path.abspath, s.split(","))) for s in args.solutions.split(";") ] else: solutions = [[]] * len(tasks) extract_dir = tempfile.mkdtemp() os.chdir(extract_dir) print("Working in %s" % extract_dir) with open("pack.zip", "wb") as f: f.write(decoded) with zipfile.ZipFile("pack.zip") as zip_file: zip_file.extractall(".") if args.sedi: validate_sedi(args.sedi) if args.admin: validate_admin(args.admin, args.password) for i, task in enumerate(tasks): if not os.path.exists(task): raise AssertionError("Task %s not included in the pack" % task) sols = solutions[i] if i < len(solutions) else [] validate_task(task, args.fuzz, args.iterations, sols) shutil.rmtree(extract_dir)
def test_encode_decode(self): password = b"fooobarr" data = b"#bellavita" encrypted = crypto.encode(password, data, b"") self.assertEqual(data, crypto.decode(password, encrypted))