#!/usr/bin/env python3 """ Simulation script for VeriFactu API certificate validation. Simulates a real user making API calls to register certificates. """ # ==================== CONFIGURABLE PASSWORD ==================== # THIS MUST MATCH THE PASSWORD IN generate_certs.py CERT_PASSWORD = "Mecedora12@" # RUTA DEL CERTIFICADO REAL REAL_CERT_PATH = r"D:\Importante\53950250R_JOSEP VICENT_MESTRE__1752317947215 - copia.p12" # ============================================================ import os import sys import base64 import json import datetime import subprocess from pathlib import Path from urllib.request import urlopen, Request from urllib.error import URLError API_URL = "http://localhost:6789" CERTS_DIR = Path(__file__).parent / "certs" # Try to import cryptography for RSA encryption try: from cryptography import x509 from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric import padding from cryptography.hazmat.backends import default_backend HAS_CRYPTO = True except ImportError: HAS_CRYPTO = False def call_api(endpoint, data=None, method="GET"): """Make HTTP call to API.""" url = f"{API_URL}{endpoint}" try: if method == "GET": req = Request(url, method="GET") else: req = Request(url, data=json.dumps(data).encode(), method="POST") req.add_header("Content-Type", "application/json") with urlopen(req, timeout=10) as response: return json.loads(response.read().decode()) except URLError as e: return {"error": str(e)} except Exception as e: return {"error": f"API call failed: {e}"} def get_public_key(): """Step 1: Get public key from API.""" print("\n" + "=" * 60) print("STEP 1: Get Public Key from API") print("=" * 60) result = call_api("/api/v1/health") print(f"Health check: {result}") if "error" in result: print(f"ERROR: API not running - {result}") return None result = call_api("/api/v1/auth/public-key") if "public_key" not in result: print(f"ERROR: No public key in response") return None pub_key_b64 = result["public_key"] pub_key = base64.b64decode(pub_key_b64) print(f"Public Key received (length: {len(pub_key)} bytes)") return pub_key def encrypt_password(public_key_pem, password): """Step 2: Encrypt password with public key (RSA).""" print("\n" + "=" * 60) print("STEP 2: Encrypt Password") print("=" * 60) if not HAS_CRYPTO: print("WARNING: cryptography not available, using base64 (NOT SECURE!)") return base64.b64encode(password.encode()).decode() try: public_key = serialization.load_pem_public_key(public_key_pem, default_backend()) encrypted = public_key.encrypt( password.encode(), padding.PKCS1v15() ) encrypted_b64 = base64.b64encode(encrypted).decode() print(f"Password encrypted (RSA)") return encrypted_b64 except Exception as e: print(f"ERROR encrypting: {e}") return None def register_certificate(cert_path, encrypted_password, test_name="default"): """Step 3: Register certificate via API.""" print("\n" + "=" * 60) print("STEP 3: Register Certificate") print("=" * 60) print(f"Certificate path: {cert_path}") print(f"Password (encrypted): {encrypted_password[:40]}...") data = { "cert_name": test_name.replace(" ", "_").replace("(", "").replace(")", ""), "cert_path": cert_path, "password_encrypted": encrypted_password } result = call_api("/api/v1/auth/register", data, method="POST") return result def test_certificate(cert_file, password, expected_result, test_name): """Test a single certificate via real API calls.""" print(f"\n{'#' * 60}") print(f"# TEST: {test_name}") print(f"# Expected: {expected_result}") print(f"{'#' * 60}") # Step 1: Get public key pub_key = get_public_key() if not pub_key: print("[X] Cannot get public key - is API running?") return # Step 2: Encrypt password enc_password = encrypt_password(pub_key, password) if not enc_password: print("[X] Cannot encrypt password") return # Step 3: Register certificate cert_path = str(CERTS_DIR / cert_file) result = register_certificate(cert_path, enc_password, test_name) print(f"\nAPI Response:") print(json.dumps(result, indent=2)) # Validate result success = result.get("success", False) error = result.get("error", "") warnings = result.get("warnings", []) if expected_result == "PASS" and success: print(f"\n[OK] TEST PASSED") elif expected_result == "FAIL" and not success: print(f"\n[OK] TEST PASSED (expected failure: {error})") elif expected_result == "PASS with WARNING" and success and warnings: print(f"\n[OK] TEST PASSED (with warnings: {warnings})") else: print(f"\n[FAIL] TEST FAILED (success={success}, error={error})") def main(): """Main test runner.""" print("=" * 60) print("VeriFactu API - Real User Simulation") print("=" * 60) print(f"\nAPI URL: {API_URL}") print(f"Certs Directory: {CERTS_DIR}") # Check if API is running print("\nChecking if API is running...") result = call_api("/api/v1/health") if "error" in result: print("ERROR: API not running!") print("Start with: ./verifactu.exe") return print(f"API is running!") print("\n" + "=" * 60) print("Running Tests via Real API Calls") print("=" * 60) test_cases = [ ("valid_365days.p12", CERT_PASSWORD, "PASS", "Valid certificate (365 days)"), ("valid_60days.p12", CERT_PASSWORD, "PASS", "Valid certificate (60 days)"), ("expired.p12", CERT_PASSWORD, "FAIL", "Expired certificate"), ("expiring_soon.p12", CERT_PASSWORD, "PASS with WARNING", "Expiring soon (15 days)"), ("not_yet_valid.p12", CERT_PASSWORD, "FAIL", "Not yet valid certificate"), ("wrong_password.p12", CERT_PASSWORD, "FAIL", "Wrong password"), (REAL_CERT_PATH, CERT_PASSWORD, "PASS", "REAL certificate with REAL password"), ] for cert_file, password, expected, test_name in test_cases: test_certificate(cert_file, password, expected, test_name) print("\n" + "=" * 60) print("ALL TESTS COMPLETED") print("=" * 60) if __name__ == "__main__": main()