def do_run(mismatches: int, key_size: int, subkey_size: int): user_id = uuid.uuid4() key = secrets.token_bytes(key_size) corrupted_key = corrupt_key(key, mismatches) server_subkeys = [ bytearray(key[index:index + subkey_size]) for index in range(0, len(key), subkey_size) ] client_subkeys = [ bytearray(corrupted_key[index:index + subkey_size]) for index in range(0, len(corrupted_key), subkey_size) ] ciphers = [] for server_subkey, client_subkey in zip(server_subkeys, client_subkeys): nonce = secrets.token_bytes(len(key) - subkey_size) server_subkey.extend(nonce) client_subkey.extend(nonce) aes = AES.new(client_subkey, AES.MODE_ECB) ciphers.append(aes.encrypt(user_id.bytes)) duration = 0 for subkey, cipher in zip(server_subkeys, ciphers): # Call rbc_validator over wsl with the UUID, the full server subkey, the client cipher, and only # the necessary subkey size set # Only extract the stderr output in verbose mode to get the actual time taken searching in text # mode, and make sure to check if the return code was zero or not try: validator_proc = subprocess.run([ "rbc_validator", "--mode=aes", "-v", "-s", str(subkey_size * 8), subkey.hex(), str(user_id), cipher.hex() ], stdout=subprocess.DEVNULL, stderr=subprocess.PIPE, universal_newlines=True, check=True, timeout=TIMEOUT) except subprocess.TimeoutExpired: return float('inf') # Get the first line such that "Clock" is contained within it. line = next(line for line in validator_proc.stderr.split('\n') if re.search(r'Clock', line)) # Get only the decimal output (in seconds) and increment duration by its value duration += float(line.split(' ')[3]) return duration
import sys import secrets import uuid from Crypto.Cipher import ChaCha20 from config import CHACHA20_NONCE_SIZE, CHACHA20_OPENSSL_NONCE_SIZE from util import corrupt_key if __name__ == "__main__": mismatches = int(sys.argv[1]) user_id = uuid.uuid4() key = secrets.token_bytes(ChaCha20.key_size) corrupted_key = corrupt_key(key, mismatches) nonce = secrets.token_bytes(CHACHA20_NONCE_SIZE) chacha20 = ChaCha20.new(key=corrupted_key, nonce=nonce) cipher = chacha20.encrypt(user_id.bytes) iv = chacha20.nonce print("Key:", key.hex()) print("Corrupted Key:", corrupted_key.hex()) print("Cipher:", cipher.hex()) print("UUID:", user_id) print("IV:", (bytes(CHACHA20_OPENSSL_NONCE_SIZE - len(iv)) + iv).hex())
import sys from Crypto.PublicKey import ECC from config import EC_CURVE from util import corrupt_key, get_ec_private_key_bytes, get_ec_public_key_bytes if __name__ == "__main__": mismatches = int(sys.argv[1]) host_priv_key = ECC.generate(curve=EC_CURVE) host_priv_key_bytes = get_ec_private_key_bytes(host_priv_key) host_pub_key_bytes = get_ec_public_key_bytes(host_priv_key, compress=False) client_priv_key_bytes = corrupt_key(host_priv_key_bytes, mismatches) client_priv_key = ECC.construct(curve=EC_CURVE, d=int.from_bytes(client_priv_key_bytes, "big")) client_pub_key_bytes = get_ec_public_key_bytes(client_priv_key, compress=False) print("EC Host Private Key: ", host_priv_key_bytes.hex()) print("EC Host Public Key: ", host_pub_key_bytes.hex()) print("EC Corrupted Private Key:", client_priv_key_bytes.hex()) print("EC Corrupted Public Key: ", client_pub_key_bytes.hex())
def simulate_fragmentation(rbc_path: Path, mismatches: int, seed_size: int, subseed_size: int, mode: str, timeout: Optional[float] = None, cutoff: bool = True, threads: int = 0) -> Tuple[float, int]: user_id = uuid.uuid4() host_seed = secrets.token_bytes(seed_size) client_seed = corrupt_key(host_seed, mismatches) host_subseeds = [ bytes(host_seed[index:index + subseed_size]) for index in range(0, len(host_seed), subseed_size) ] client_subseeds = [ bytes(client_seed[index:index + subseed_size]) for index in range(0, len(client_seed), subseed_size) ] args = [] for host_subseed, client_subseed in zip(host_subseeds, client_subseeds): nonce = secrets.token_bytes(len(host_seed) - subseed_size) host_subkey = host_subseed + nonce client_subkey = client_subseed + nonce subargs = [host_subkey.hex()] if mode == "aes": aes = AES.new(client_subkey, AES.MODE_ECB) subargs += [aes.encrypt(user_id.bytes).hex(), str(user_id)] elif mode == "chacha20": chacha20_nonce = secrets.token_bytes(CHACHA20_NONCE_SIZE) chacha20 = ChaCha20.new(key=client_subkey, nonce=chacha20_nonce) client_key = chacha20.encrypt(user_id.bytes) iv = chacha20.nonce iv = bytes(CHACHA20_OPENSSL_NONCE_SIZE - len(iv)) + iv subargs += [client_key.hex(), user_id.hex, iv.hex()] elif mode == "ecc": client_priv_key = ECC.construct(curve=EC_CURVE, d=int.from_bytes( client_subkey, "big")) subargs += [ get_ec_public_key_bytes(client_priv_key, compress=False).hex() ] elif mode in hash_modes: h = hashlib.new(mode.replace('-', '_'), client_subkey) subargs += [h.hexdigest()] elif mode == "kang12": subargs += [KangarooTwelve(client_subkey, b'', KANG12_SIZE).hex()] else: print(f"Error: Mode '{mode}' is not recognized.", file=sys.stderr) sys.exit(1) args.append(subargs) duration = 0 key_count = 0 for subargs in args: # Call rbc_validator over wsl with the UUID, the full server subkey, the client cipher, and only # the necessary subkey size set # Only extract the stderr output in verbose mode to get the actual time taken searching in text # mode, and make sure to check if the return code was zero or not env_args = [] rbc_path_abs = rbc_path.resolve() if sys.platform == "win32": env_args.append("wsl") rbc_path_abs = PurePosixPath("/mnt", rbc_path_abs.drive[:-1].lower(), *rbc_path_abs.parts[1:]) env_args += [ rbc_path_abs.as_posix(), f"--mode={mode}", f"--subkey={subseed_size * 8}", f"--threads={threads}", "-v", "-c" ] if not cutoff: env_args.append("-a") env_args += subargs try: validator_proc = subprocess.run( env_args, stdout=subprocess.DEVNULL, stderr=subprocess.PIPE, universal_newlines=True, check=True, timeout=None if timeout is None else timeout - duration) except subprocess.TimeoutExpired: return float("inf"), key_count lines = [line for line in validator_proc.stderr.split("\n")] # Get the first line such that "Clock" is contained within it. clock_line = next(line for line in lines if re.search(r"Clock", line)) count_line = next(line for line in lines if re.search(r"searched", line)) # Get only the decimal output (in seconds) and increment duration by its value duration += float(clock_line.split(" ")[3]) key_count += int(count_line.split(" ")[3]) return duration, key_count
import hashlib import secrets import sys from util import corrupt_key SEED_SIZE = 32 SALT_SIZE = 16 if __name__ == "__main__": mismatches = int(sys.argv[1]) is_salt = sys.argv[2] == "True" host_seed = secrets.token_bytes(SEED_SIZE) client_seed = corrupt_key(host_seed, mismatches) salt = secrets.token_bytes(SALT_SIZE) if is_salt else bytes() if is_salt: print("Salt: ", salt.hex()) print("Host Seed: ", host_seed.hex()) print("Host Digest: ", hashlib.sha1(host_seed + salt).hexdigest()) print("Client Seed: ", client_seed.hex()) print("Client Digest:", hashlib.sha1(client_seed + salt).hexdigest())