#!/usr/bin/env python3
"""Independent verifier for the Markovian transparency-log checkpoint.

Fetches https://log.markovianprotocol.com/checkpoint and verifies every
Ed25519 witness cosignature (C2SP cosignature/v1) against keys pinned IN
THIS FILE — each key was collected from the witness operator's own
published page, cited next to it. The log operator is not trusted for any
key. Read the whole script before running it; that is the point of it.

Policy: the checkpoint is WITNESSED if at least 4 of the 7 pinned
witnesses verify. Fewer than 4 means treat it as operator-only.
Two witnesses also emit ML-DSA-44 (post-quantum) cosignatures; this
script checks the classical signatures only.

Requires: python3 + the 'cryptography' package (pip install cryptography).
Usage:    python3 verify_checkpoint.py [checkpoint-file]
Exit 0 = policy met; exit 1 = not met.
"""
import base64, hashlib, struct, sys, urllib.request

CHECKPOINT_URL = "https://log.markovianprotocol.com/checkpoint"
THRESHOLD = 4

# name+keyid+base64(0x04||ed25519_pubkey) — source cited per line.
PINNED = [
    ("witness.stagemole.eu+67f7aea0+BEqSG3yu9YrmcM3BHvQYTxwFj3uSWakQepafafpUqklv",
     "https://witness.stagemole.eu/about"),
    ("transparency.dev/DEV:witness-little-garden+d8042a87+BCtusOxINQNUTN5Oj8HObRkh2yHf/MwYaGX4CPdiVEPM",
     "https://transparency.dev/witnesses/"),
    ("staging.witness.transparency.goog/ring-any-bells+2e1a8dc9+BG5JTpLc3FJtwzgh1Uv+Qelz9qeOH2bfWjS1s0s+y4rL",
     "https://transparency.dev/witnesses/"),
    ("rgdd.se/poc-witness+db03732e+BCjJKlo6BU0xfIb8LutqerIFTWIXEA0L5n3tW3QyPFgG",
     "https://www.rgdd.se/poc-witness/about"),
    ("witness1.smartit.nu/witness1+a48c820f+BPSFWg9G6KPiO7QPryYO5Xq4oYJJ+kAvLKLSimDhoxMO",
     "https://witness1.smartit.nu/witness1/about.txt"),
    ("remora.n621.de+da77ade7+BOvN63jn/bLvkieywe8R6UYAtVtNbZpXh34x7onlmtw2",
     "https://remora.n621.de/"),
    ("witness.navigli.sunlight.geomys.org+a3e00fe2+BNy/co4C1Hn1p+INwJrfUlgz7W55dSZReusH/GhUhJ/G",
     "https://navigli.sunlight.geomys.org/"),
]


def parse_vkey(vkey):
    # base64 may itself contain '+', so split on the first two only.
    name, keyid_hex, b64 = vkey.split("+", 2)
    blob = base64.b64decode(b64)
    if blob[0] != 0x04:
        raise ValueError(f"{name}: not an Ed25519 (0x04) vkey")
    pub = blob[1:]
    # keyid self-check: SHA-256(name || 0x0A || 0x04 || pub)[:4]
    kid = hashlib.sha256(name.encode() + b"\n\x04" + pub).digest()[:4]
    if kid.hex() != keyid_hex:
        raise ValueError(f"{name}: keyid mismatch (pin corrupted?)")
    return name, bytes.fromhex(keyid_hex), pub


def main():
    from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey
    from cryptography.exceptions import InvalidSignature

    if len(sys.argv) > 1:
        raw = open(sys.argv[1], "rb").read()
    else:
        raw = urllib.request.urlopen(CHECKPOINT_URL, timeout=15).read()

    text = raw.decode()
    body, _, sigblock = text.partition("\n\n")
    note_body = body + "\n"          # origin, tree size, root hash
    lines = [l for l in sigblock.strip().split("\n") if l.startswith("— ")]
    print(note_body.rstrip())
    print(f"-- {len(lines)} signature lines --")

    keys = {}
    for vkey, src in PINNED:
        name, kid, pub = parse_vkey(vkey)
        keys[(name, kid)] = (pub, src)

    ok = 0
    seen = set()
    for line in lines:
        _, name, b64sig = line.split(" ", 2)
        blob = base64.b64decode(b64sig)
        if len(blob) != 76:          # keyid(4)+timestamp(8)+ed25519(64)
            continue                 # ML-DSA-44 or other scheme: skip here
        kid, ts_raw, sig = blob[:4], blob[4:12], blob[12:]
        if (name, kid) not in keys:
            continue                 # not a pinned witness (e.g. the operator)
        ts = struct.unpack(">Q", ts_raw)[0]
        msg = b"cosignature/v1\ntime " + str(ts).encode() + b"\n" + note_body.encode()
        pub, src = keys[(name, kid)]
        try:
            Ed25519PublicKey.from_public_bytes(pub).verify(sig, msg)
            if name not in seen:
                seen.add(name); ok += 1
            print(f"  OK   {name}   (key from {src})")
        except InvalidSignature:
            print(f"  FAIL {name}   signature did not verify")

    print(f"\n{ok} of {len(PINNED)} pinned witnesses verified; policy requires {THRESHOLD}.")
    if ok >= THRESHOLD:
        print("WITNESSED: policy met.")
        sys.exit(0)
    print("NOT WITNESSED under policy: treat as operator-only.")
    sys.exit(1)


if __name__ == "__main__":
    main()
