#!/usr/bin/env python3
"""verify_trc.py —— 独立开源验签脚本（v2.2 §7.5：去中心化验证，仅依赖 cryptography）。

任何第三方取得证书 JSON 后可脱离御麒麟服务独立验证：
  python3 verify_trc.py <cert.json> [--jwks jwks.json]

验证项：①撤销状态（离线模式跳过）②JWKS 公钥交叉核验 ③EdDSA 签名
④canonical JSON 重算 ⑤有效期。退出码 0=TRUSTED。
"""
import argparse
import json
import sys
from datetime import datetime
from pathlib import Path

from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey

BASE = Path(__file__).resolve().parent


def b64url_enc(data: bytes) -> str:
    import base64
    return base64.urlsafe_b64encode(data).decode("ascii").rstrip("=")


def b64url_dec(s: str) -> bytes:
    import base64
    return base64.urlsafe_b64decode(s + "=" * (-len(s) % 4))


def canonical_json(obj) -> str:
    import unicodedata

    def nfc(o):
        if isinstance(o, str):
            return unicodedata.normalize("NFC", o)
        if isinstance(o, list):
            return [nfc(x) for x in o]
        if isinstance(o, dict):
            return {nfc(k): nfc(v) for k, v in o.items()}
        return o
    return json.dumps(nfc(obj), ensure_ascii=False, sort_keys=True,
                      separators=(",", ":"), allow_nan=False)


def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("cert_json")
    ap.add_argument("--jwks", default=str(BASE / "keys_public" / "jwks.json"))
    args = ap.parse_args()
    cert = json.loads(Path(args.cert_json).read_text(encoding="utf-8"))
    proof = cert.pop("proof")
    jwks = json.loads(Path(args.jwks).read_text(encoding="utf-8"))
    jwk = next((k for k in jwks["keys"] if k["kid"] == proof.get("kid")), None)
    checks = []

    def okc(name, passed, detail=""):
        checks.append((name, passed, detail))
        return passed

    if not okc("jwks-kid", jwk is not None, proof.get("kid", "")):
        print("RESULT: UNTRUSTED（JWKS 无此公钥）")
        return 1
    header = {"alg": "EdDSA", "kid": proof["kid"], "typ": "JWT"}
    signing_input = (b64url_enc(json.dumps(header, separators=(",", ":")).encode())
                     + "." + b64url_enc(canonical_json(cert).encode("utf-8")))
    try:
        Ed25519PublicKey.from_public_bytes(b64url_dec(jwk["x"])).verify(
            b64url_dec(proof["signature"]), signing_input.encode())
        okc("ed25519-signature", True)
    except Exception as e:
        okc("ed25519-signature", False, type(e).__name__)
    exp = cert.get("expires_at", "")
    exp_dt = datetime.fromisoformat(exp) if exp else None
    okc("not-expired",
        exp_dt is not None and exp_dt > datetime.now(exp_dt.tzinfo))
    for name, passed, detail in checks:
        print(f"{'✅' if passed else '❌'} {name} {detail}")
    trusted = all(p for _, p, _ in checks)
    print(f"RESULT: {'TRUSTED' if trusted else 'UNTRUSTED'}  "
          f"certificate_id={cert.get('certificate_id')}  "
          f"evidence_root={cert['credentialSubject']['evidence_root'][:23]}…")
    return 0 if trusted else 1


if __name__ == "__main__":
    sys.exit(main())
