Moved to a repo https://github.com/up-n-atom/xmlc
Last active
May 29, 2025 21:35
-
-
Save up-n-atom/ab34b61e0d512bf32f496227b3211881 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import argparse | |
| from Cryptodome.Cipher import AES | |
| import hashlib | |
| import io | |
| import struct | |
| import sys | |
| import time | |
| from typing import BinaryIO | |
| import zlib | |
| XMLC = b'XMLC' | |
| Y2K = 0x20000301 | |
| def genkeys(hdr: bytes) -> tuple[bytes]: | |
| magic, epoch = struct.unpack_from('<4sI', hdr) | |
| if magic != XMLC and epoch != Y2K: | |
| raise ValueError('Bad XMLC header') | |
| # aes-key, iv | |
| return (hashlib.md5(b'\x12\x34\x56\x78' + hdr).digest() + hashlib.md5(b'\x0a\xbc\xd7\x75').digest(), | |
| hashlib.md5(b'\x91\x2a\x54\xb7').digest()) | |
| def encrypt(in_file: BinaryIO, out_file: BinaryIO) -> None: | |
| key, iv = genkeys(in_file.read(32)) | |
| cipher = AES.new(key, AES.MODE_OFB, iv=iv) | |
| out_file.write(cipher.encrypt(in_file.read())) | |
| def decompress(in_file: BinaryIO, out_file: BinaryIO) -> None: | |
| with io.BytesIO() as out_buf: | |
| encrypt(in_file, out_buf) | |
| out_file.write(zlib.decompress(out_buf.getbuffer(), wbits=31)) | |
| def compress(in_file: BinaryIO, out_file: BinaryIO) -> None: | |
| hdr = struct.pack('<4s2I20x', XMLC, Y2K, int(time.time())) | |
| out_file.write(hdr) | |
| with io.BytesIO() as in_buf: | |
| in_buf.write(hdr) | |
| in_buf.write(zlib.compress(in_file.read(), wbits=31)) | |
| in_buf.seek(0) | |
| encrypt(in_buf, out_file) | |
| if __name__ == '__main__': | |
| parser = argparse.ArgumentParser(description='XMLC tool') | |
| parser.add_argument('-c', '--compress', action='store_true') | |
| parser.add_argument("infile", | |
| type=argparse.FileType('rb')) | |
| parser.add_argument("outfile", | |
| type=argparse.FileType('wb')) | |
| args = parser.parse_args() | |
| with args.infile as in_file, args.outfile as out_file: | |
| action = compress if args.compress else decompress | |
| try: | |
| action(in_file, out_file) | |
| except (ValueError, zlib.error) as e: | |
| print(e, file=sys.stderr) | |
| sys.exit(1) | |
| sys.exit(0) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment