Files
elysium/tests/test_decrypt.py
tomas.kracmar ffccedb439 refactor: move provider-side tools to tools/
Prepare-KHDBStorage.ps1 (publishes the KHDB) and decrypt.py
(decrypts client hash exports on the provider's cracking machine)
are only ever run by the tool provider, but sat next to the client
scripts that every customer clones. Moved both to tools/ so the
client surface (root wrappers + src/Elysium) is separate from
provider tooling; packaging the module later ships only src/Elysium.

Prepare-KHDBStorage.ps1 now resolves Elysium.Common.ps1 and the
default ElysiumSettings.txt from the repo root (one level up) instead
of its own folder. tests/test_decrypt.py imports decrypt from tools/.
README and AGENTS paths updated; AGENTS' structure listing also gets
the module lines back after the settings sample, where they belong.

Verified: decrypt round trip passes from the new location, and
tools/Prepare-KHDBStorage.ps1 -SkipUpload runs from the repo root and
produces a package (manifest, 256 shards, khdb-clean.txt).
2026-11-04 13:04:10 +01:00

54 lines
2.0 KiB
Python

# ELY2 round trip: encrypt with the real Protect-FileWithAES (src/Elysium/Private/Crypto.ps1, via
# pwsh), decrypt with decrypt.py. Catches any drift between the two sides of the format.
# Run: python3 tests/test_decrypt.py (needs pwsh on PATH and pycryptodome)
import os
import subprocess
import sys
import tempfile
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, os.path.join(ROOT, 'tools'))
import decrypt # noqa: E402
ENCRYPT_PS1 = r'''
param($Crypto, $In, $Out, $Pass)
$ErrorActionPreference = 'Stop'
. $Crypto
Protect-FileWithAES -InputFile $In -OutputFile $Out -Passphrase $Pass 6>$null
'''
def encrypt_with_powershell(plaintext: bytes, passphrase: str) -> bytes:
with tempfile.TemporaryDirectory() as d:
src, dst, ps1 = (os.path.join(d, n) for n in ('in.zip', 'out.enc', 'encrypt.ps1'))
with open(src, 'wb') as f:
f.write(plaintext)
with open(ps1, 'w', encoding='utf-8') as f:
f.write(ENCRYPT_PS1)
subprocess.run(['pwsh', '-NoProfile', '-File', ps1,
'-Crypto', os.path.join(ROOT, 'src', 'Elysium', 'Private', 'Crypto.ps1'),
'-In', src, '-Out', dst, '-Pass', passphrase], check=True)
with open(dst, 'rb') as f:
return f.read()
def assert_rejected(blob: bytes, passphrase: str):
try:
decrypt.decrypt(blob, passphrase)
except ValueError as e:
assert 'HMAC' in str(e), e
else:
raise AssertionError('tampered/wrong-passphrase input was accepted')
plaintext = os.urandom(1000)
for passphrase in ('correct horse battery staple', 'pässwörd-€'): # ASCII + non-ASCII
blob = encrypt_with_powershell(plaintext, passphrase)
assert blob[:4] == b'ELY2', blob[:4]
assert decrypt.decrypt(blob, passphrase) == plaintext, passphrase
assert_rejected(blob, 'wrong passphrase')
assert_rejected(blob[:40] + bytes([blob[40] ^ 1]) + blob[41:], passphrase) # flipped ciphertext bit
print('ok')