#!/usr/bin/env python3
import base64, json, sys
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey

PREFIX = b"FARPY_RECEIPT_V1\n"
STRIP_FIELDS = ("sig","sig_alg","sig_pub","sig_v")

def canon(obj):
    return json.dumps(obj, sort_keys=True, separators=(",",":"), ensure_ascii=False).encode("utf-8")

def load_pub(pem_path):
    pem=open(pem_path,"rb").read()
    pk=serialization.load_pem_public_key(pem)
    if not isinstance(pk, Ed25519PublicKey):
        raise SystemExit("public key is not Ed25519")
    return pk

def verify(receipt_path, pub_pem_path):
    r=json.load(open(receipt_path,"r",encoding="utf-8"))
    sig_b64=r.get("sig")
    if not isinstance(sig_b64,str):
        raise SystemExit("missing sig")
    obj=dict(r)
    for k in STRIP_FIELDS: obj.pop(k,None)
    msg=PREFIX+canon(obj)
    sig=base64.b64decode(sig_b64)
    pk=load_pub(pub_pem_path)
    # enforce that receipt sig_pub matches the pinned public key
    pub_b64=r.get("sig_pub")
    if not isinstance(pub_b64,str):
        raise SystemExit("missing sig_pub")
    try:
        pub_raw=base64.b64decode(pub_b64)
    except Exception:
        raise SystemExit("bad sig_pub b64")
    pk_raw=pk.public_bytes(encoding=serialization.Encoding.Raw, format=serialization.PublicFormat.Raw)
    if pub_raw!=pk_raw:
        raise SystemExit("sig_pub_mismatch")
    pk.verify(sig,msg)
    return True

if __name__=="__main__":
    if len(sys.argv)!=3:
        print("usage: verify.py /path/to/receipt.json /path/to/public_key.pem"); sys.exit(2)
    verify(sys.argv[1],sys.argv[2])
    print("OK:VERIFY")
