"""Cross-check the Python SDK against the canonical wire-format test vectors at ../../tests/crosscheck/vector.json. These vectors are also exercised by the Rust and TS SDKs. Any new SDK must pass every fixture in vector.json — that's how we guarantee wire-format compatibility across languages. Run with: `pytest -q` from the package root, OR `python -m pytest`. """ from __future__ import annotations import json from pathlib import Path import pytest from keysat_licensing_client import ( PublicKey, Verifier, LicensingError, has_entitlement, hash_fingerprint, is_expired_at, parse_license_key, ) # Locate vector.json relative to this file. The tests directory lives # at licensing-client-python/tests/, the vector lives at # tests/crosscheck/vector.json (repo root). Walk up until we find it. def _vectors_path() -> Path: here = Path(__file__).resolve().parent for ancestor in [here, *here.parents]: candidate = ancestor / "tests" / "crosscheck" / "vector.json" if candidate.exists(): return candidate pytest.skip("crosscheck vector.json not found; run from repo with tests/ tree") @pytest.fixture(scope="module") def vectors() -> dict: with _vectors_path().open() as f: return json.load(f) @pytest.fixture(scope="module") def verifier(vectors: dict) -> Verifier: return Verifier(PublicKey.from_pem(vectors["publicKeyPem"])) # ------------------------------------------------------------------ # v1 fixture: legacy fixed-74 layout, fingerprint-bound, no expiry, # no entitlements. # ------------------------------------------------------------------ def test_v1_parses(vectors: dict) -> None: parsed = parse_license_key(vectors["v1"]["licenseKey"]) exp = vectors["v1"]["expected"] assert parsed.payload.version == exp["version"] assert str(parsed.payload.product_id) == exp["productUuid"] assert str(parsed.payload.license_id) == exp["licenseUuid"] assert parsed.payload.issued_at == exp["issuedAt"] assert parsed.payload.expires_at == exp["expiresAt"] assert parsed.payload.flags == exp["flags"] assert parsed.payload.is_fingerprint_bound is exp["isFingerprintBound"] assert parsed.payload.is_trial is exp["isTrial"] assert parsed.payload.entitlements == exp["entitlements"] assert parsed.payload.fingerprint_hash.hex() == exp["fingerprintHashHex"] def test_v1_verifies(verifier: Verifier, vectors: dict) -> None: ok = verifier.verify(vectors["v1"]["licenseKey"]) assert str(ok.product_id) == vectors["v1"]["expected"]["productUuid"] def test_v1_tamper_detected(verifier: Verifier, vectors: dict) -> None: key = vectors["v1"]["licenseKey"] # Flip one char in the payload section. The signature won't match. payload_start = key.index("-") + 1 tampered = key[:payload_start] + ("B" if key[payload_start] != "B" else "C") + key[payload_start + 1 :] with pytest.raises(LicensingError) as excinfo: verifier.verify(tampered) assert excinfo.value.kind in ("bad_signature", "bad_format") # ------------------------------------------------------------------ # v2 fixture: trial, fingerprint-bound, explicit expiry, two entitlements. # Stresses the variable-length tail parser. # ------------------------------------------------------------------ def test_v2_parses(vectors: dict) -> None: parsed = parse_license_key(vectors["v2"]["licenseKey"]) exp = vectors["v2"]["expected"] assert parsed.payload.version == exp["version"] assert str(parsed.payload.product_id) == exp["productUuid"] assert str(parsed.payload.license_id) == exp["licenseUuid"] assert parsed.payload.issued_at == exp["issuedAt"] assert parsed.payload.expires_at == exp["expiresAt"] assert parsed.payload.flags == exp["flags"] assert parsed.payload.is_fingerprint_bound is exp["isFingerprintBound"] assert parsed.payload.is_trial is exp["isTrial"] assert parsed.payload.entitlements == exp["entitlements"] def test_v2_verifies(verifier: Verifier, vectors: dict) -> None: ok = verifier.verify(vectors["v2"]["licenseKey"]) assert ok.is_trial assert ok.is_fingerprint_bound assert len(ok.entitlements) == len(vectors["v2"]["expected"]["entitlements"]) def test_v2_expiry_boundary(vectors: dict) -> None: parsed = parse_license_key(vectors["v2"]["licenseKey"]) expires_at = parsed.payload.expires_at assert is_expired_at(parsed.payload, expires_at) is True assert is_expired_at(parsed.payload, expires_at - 1) is False def test_v2_entitlements(vectors: dict) -> None: parsed = parse_license_key(vectors["v2"]["licenseKey"]) for slug in vectors["v2"]["expected"]["entitlements"]: assert has_entitlement(parsed.payload, slug) assert has_entitlement(parsed.payload, "definitely-not-a-real-entitlement") is False # ------------------------------------------------------------------ # v2_perpetual_unbound — common case for paid purchase: v2, no expiry, # no fingerprint binding, no entitlements. # ------------------------------------------------------------------ def test_v2_perpetual_unbound_parses(vectors: dict) -> None: if "v2_perpetual_unbound" not in vectors: pytest.skip("vector.json doesn't include v2_perpetual_unbound") parsed = parse_license_key(vectors["v2_perpetual_unbound"]["licenseKey"]) assert parsed.payload.version == 2 assert parsed.payload.expires_at == 0 assert parsed.payload.is_fingerprint_bound is False def test_v2_perpetual_unbound_verifies(verifier: Verifier, vectors: dict) -> None: if "v2_perpetual_unbound" not in vectors: pytest.skip("vector.json doesn't include v2_perpetual_unbound") verifier.verify(vectors["v2_perpetual_unbound"]["licenseKey"]) # ------------------------------------------------------------------ # Cross-language fingerprint-hash compatibility. # ------------------------------------------------------------------ def test_hash_fingerprint_matches_python_stdlib() -> None: import hashlib raw = "hello" expected = hashlib.sha256(raw.encode()).hexdigest() assert hash_fingerprint(raw) == expected # ------------------------------------------------------------------ # Negative cases. # ------------------------------------------------------------------ def test_bad_format_short_key() -> None: with pytest.raises(LicensingError) as excinfo: parse_license_key("notakey") assert excinfo.value.kind == "bad_format" def test_bad_format_wrong_prefix() -> None: with pytest.raises(LicensingError) as excinfo: parse_license_key("LIC9-AAAA-BBBB") assert excinfo.value.kind == "bad_format"