From ff49d9ba1dd41b727d5bc0eb2f7ced601e128875 Mon Sep 17 00:00:00 2001 From: Justin Bollinger Date: Mon, 26 Jan 2026 22:05:19 -0500 Subject: [PATCH] pipal tests --- hate_crack/api.py | 9 ++++ tests/test_pipal.py | 80 +++++++++++++++++++++++++++++++++ tests/test_pipal_integration.py | 43 ++++++++++++++++++ 3 files changed, 132 insertions(+) create mode 100644 tests/test_pipal.py create mode 100644 tests/test_pipal_integration.py diff --git a/hate_crack/api.py b/hate_crack/api.py index f33cd6f..724af6b 100644 --- a/hate_crack/api.py +++ b/hate_crack/api.py @@ -1,6 +1,7 @@ import json import os import threading +import time from queue import Queue import shutil from typing import Callable, Tuple @@ -80,6 +81,14 @@ def register_torrent_cleanup(): _TORRENT_CLEANUP_REGISTERED = True def fetch_all_weakpass_wordlists_multithreaded(total_pages=67, threads=10, output_file="weakpass_wordlists.json"): + if os.path.isfile(output_file): + try: + mtime = os.path.getmtime(output_file) + if (time.time() - mtime) < 24 * 60 * 60: + print(f"[i] Using cached wordlist file: {output_file}") + return + except Exception: + pass wordlists = [] lock = threading.Lock() q = Queue() diff --git a/tests/test_pipal.py b/tests/test_pipal.py new file mode 100644 index 0000000..08da3dd --- /dev/null +++ b/tests/test_pipal.py @@ -0,0 +1,80 @@ +import os + + +def _write_executable(path, content): + path.write_text(content) + os.chmod(path, 0o755) + + +def test_pipal_runs_and_parses_basewords(hc_module, tmp_path, capsys): + hc = hc_module + hc.hcatHashType = "0" + hc.pipal_count = 3 + hc.hcatHashFile = str(tmp_path / "hashes") + + out_path = tmp_path / "hashes.out" + out_path.write_text( + "hash1:password123\n" + "hash2:$HEX[70617373313233]\n" + ) + + pipal_stub = tmp_path / "pipal_stub.py" + _write_executable( + pipal_stub, + "#!/usr/bin/env python3\n" + "import sys\n" + "out = None\n" + "if '--output' in sys.argv:\n" + " out = sys.argv[sys.argv.index('--output') + 1]\n" + "if not out:\n" + " out = sys.argv[-1]\n" + "with open(out, 'w') as f:\n" + " f.write('Top 3 base words\\n')\n" + " f.write('pass123 10\\n')\n" + " f.write('letmein 5\\n')\n" + " f.write('welcome 3\\n')\n" + ) + hc.pipalPath = str(pipal_stub) + + result = hc.pipal() + captured = capsys.readouterr() + + assert result == ["pass123", "letmein", "welcome"] + assert "Pipal file is at" in captured.out + + passwords_file = tmp_path / "hashes.passwords" + assert passwords_file.exists() + content = passwords_file.read_text() + assert "password123" in content + assert "pass123" in content + + +def test_pipal_missing_out_returns_empty(hc_module, tmp_path, capsys): + hc = hc_module + hc.hcatHashType = "0" + hc.pipal_count = 3 + hc.hcatHashFile = str(tmp_path / "hashes") + + pipal_stub = tmp_path / "pipal_stub.py" + _write_executable( + pipal_stub, + "#!/usr/bin/env python3\n" + "import sys\n" + "out = None\n" + "if '--output' in sys.argv:\n" + " out = sys.argv[sys.argv.index('--output') + 1]\n" + "if not out:\n" + " out = sys.argv[-1]\n" + "with open(out, 'w') as f:\n" + " f.write('Top 3 base words\\n')\n" + " f.write('pass123 10\\n')\n" + " f.write('letmein 5\\n')\n" + " f.write('welcome 3\\n')\n" + ) + hc.pipalPath = str(pipal_stub) + + result = hc.pipal() + captured = capsys.readouterr() + + assert result == [] + assert "No hashes were cracked" in captured.out diff --git a/tests/test_pipal_integration.py b/tests/test_pipal_integration.py new file mode 100644 index 0000000..6017a4f --- /dev/null +++ b/tests/test_pipal_integration.py @@ -0,0 +1,43 @@ +import os +import subprocess + + +import json + +def test_pipal_executable_and_runs(tmp_path): + # Read pipalPath from config.json + config_path = os.path.join(os.path.dirname(__file__), '..', 'config.json') + with open(config_path, 'r') as f: + config = json.load(f) + pipal_path = config.get('pipalPath') + if not pipal_path or not os.path.isfile(pipal_path): + import pytest + pytest.skip("pipalPath not configured or file missing") + + if not os.access(pipal_path, os.X_OK): + raise AssertionError( + f"pipalPath exists but is not executable: {pipal_path}. " + "Ensure pipal is installed/compiled and has execute permissions." + ) + + input_file = tmp_path / "pipal_input.txt" + input_file.write_text("password\npassword123\nletmein\n") + output_file = tmp_path / "pipal_output.txt" + + result = subprocess.run( + [pipal_path, str(input_file), "-t", "3", "--output", str(output_file)], + capture_output=True, + text=True, + ) + + if result.returncode != 0: + raise AssertionError( + "pipal did not run successfully. " + f"returncode={result.returncode}, stdout={result.stdout}, stderr={result.stderr}" + ) + + if not output_file.exists(): + raise AssertionError("pipal did not produce an output file; it may need to be compiled.") + + content = output_file.read_text() + assert "Top 3 base words" in content