#!/usr/bin/env python import argparse import binascii import os import platform import shutil import sys from Crypto.Cipher import AES from Crypto.Hash import HMAC, SHA256 from Crypto.Protocol.KDF import PBKDF2 from Crypto.Util import Padding from random import SystemRandom random = SystemRandom() def take(bytearr, start, count): return bytearr[start:start+count] def write_file(path, content): if os.path.exists(path): randomsuffix = binascii.hexlify(random.randbytes(4)).decode() backupfile = path + f".{randomsuffix}.backup" print(f"making backup copy of {path} to {backupfile}", file=sys.stderr) shutil.copy(path, backupfile) print(f"writing data to {path}", file=sys.stderr) mode = "wb" if isinstance(content, bytes) else "w" with open(path, "wb") as f: f.write(content.encode() if isinstance(content, str) else content) PASSW = "e6552ddf3ac5c8755a82870d91273a63eab0da1e" KDF_ITER_CNT = 10000 KEY_BYTE_LEN = 32 SALT_BYTE_LEN = 8 IV_BYTE_LEN = 16 NOTSECRETPAYLOAD = b"4af85e84255b077ad890dba297e811b7d016add1" HMAC_BYTE_LEN = 32 def encrypt(data_raw): encoded_data = NOTSECRETPAYLOAD cryptsalt = random.randbytes(SALT_BYTE_LEN) encoded_data += cryptsalt authsalt = random.randbytes(SALT_BYTE_LEN) encoded_data += authsalt cryptkey = PBKDF2(PASSW, cryptsalt, KEY_BYTE_LEN, KDF_ITER_CNT) authkey = PBKDF2(PASSW, authsalt, KEY_BYTE_LEN, KDF_ITER_CNT) iv = random.randbytes(IV_BYTE_LEN) encoded_data += iv ciphertext = AES.new(cryptkey, AES.MODE_CBC, iv).encrypt( Padding.pad(data_raw, block_size=AES.block_size) ) encoded_data += ciphertext tag = HMAC.new(authkey, encoded_data, SHA256).digest() return encoded_data + tag def decrypt(data_raw): notsecret_len = len(NOTSECRETPAYLOAD) cryptsalt = take(data_raw, notsecret_len, SALT_BYTE_LEN) # authsalt = take(data_raw, NONSECRET_LEN+SALT_BYTE_LEN, SALT_BYTE_LEN) cryptkey = PBKDF2(PASSW, cryptsalt, KEY_BYTE_LEN, KDF_ITER_CNT) # authkey = PBKDF2(PASSW, authsalt, KEY_BYTE_LEN, KDF_ITER_CNT) iv = take(data_raw, notsecret_len + SALT_BYTE_LEN * 2, IV_BYTE_LEN) ciphertext_start = notsecret_len + SALT_BYTE_LEN * 2 + IV_BYTE_LEN ciphertext = data_raw[ciphertext_start:-HMAC_BYTE_LEN] return Padding.unpad( AES.new(cryptkey, AES.MODE_CBC, iv).decrypt(ciphertext), block_size=AES.block_size ) HEADER_LEN = 3 PROFILE_ID_LEN = 64 PLAINTEXT_PROFILE_TYPE = b"v2n" XML_HEADER_START = b'