VerifactuMidAPI/test/simulate.py

212 lines
6.5 KiB
Python

#!/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()