#!/usr/bin/env python3 """FeedOracle Treasury Audit - Response Verifier Usage: python3 verify_response.py response.json Deps: pip install ecdsa """ import json, hashlib, base64, sys from ecdsa import VerifyingKey, SECP256k1, BadSignatureError JWKS_URL = "https://feedoracle.io/.well-known/jwks.json" # Embedded public key (feedoracle-prod-2026) PUB_X = "agNOLX9EhX3OyJ59GoeToUMY4NyFTo0CaXjq_NKzBWc" PUB_Y = "TXHvNEUK1Ps22zbHVF1ZkRYnGwIJ-t3Xqp9TgR1WQRI" def verify(path): d = json.load(open(path)) ev = d.get("evidence") if not ev: print("ERROR: No evidence block found"); return False print(f"Request ID: {d.get('request_id')}") print(f"Schema: {d.get('schema_version')}") print(f"Timestamp: {ev.get('timestamp')}") # Step 1: Remove /evidence, canonicalize, hash body = {k: v for k, v in d.items() if k not in ("evidence", "manifest_id")} canon = json.dumps(body, sort_keys=True, separators=(",", ":")) computed = hashlib.sha256(canon.encode()).hexdigest() claimed = ev["content_hash"]["hex"] print(f"\n[Hash Verification]") print(f" Claimed: {claimed}") print(f" Computed: {computed}") if computed != claimed: print(" RESULT: HASH MISMATCH ❌"); return False print(" RESULT: HASH MATCH ✅") # Step 2: Load public key, verify signature sig_hex = ev["signature"]["value"] if not sig_hex: print("\n RESULT: NO SIGNATURE ⚠️"); return False if sig_hex.startswith("0x"): sig_hex = sig_hex[2:] x = base64.urlsafe_b64decode(PUB_X + "==") y = base64.urlsafe_b64decode(PUB_Y + "==") vk = VerifyingKey.from_string(x + y, curve=SECP256k1) digest = bytes.fromhex(claimed) sig_bytes = bytes.fromhex(sig_hex) print(f"\n[Signature Verification]") print(f" Algorithm: {ev['signature']['alg']}") print(f" Key ID: {ev.get('key_id')}") try: vk.verify_digest(sig_bytes, digest) print(" RESULT: SIGNATURE VALID ✅") return True except BadSignatureError: print(" RESULT: SIGNATURE INVALID ❌") return False def verify_release(d="."): """Verify RELEASE.json: hash + signature + file checksums.""" import os rpath = os.path.join(d, "RELEASE.json") spath = os.path.join(d, "RELEASE.json.sig") hpath = os.path.join(d, "RELEASE.json.sha256") m = json.load(open(rpath)) print(f"Release: {m.get('release_id')} Kit: {m.get('kit_version')}") print(f"Issued: {m.get('generated_at')} by {m.get('issuer')}") raw = open(rpath, "rb").read() h = hashlib.sha256(raw).hexdigest() claimed = open(hpath).read().strip() print(f"\n[Manifest Hash]") print(f" Computed: {h}") print(f" Claimed: {claimed}") if h != claimed: print(" RESULT: HASH MISMATCH"); return False print(" RESULT: HASH MATCH") sig_obj = json.load(open(spath)) sig_hex = sig_obj["signature"] if sig_hex.startswith("0x"): sig_hex = sig_hex[2:] x = base64.urlsafe_b64decode(PUB_X + "==") y = base64.urlsafe_b64decode(PUB_Y + "==") vk = VerifyingKey.from_string(x + y, curve=SECP256k1) print(f"\n[Manifest Signature]") try: vk.verify_digest(bytes.fromhex(sig_hex), bytes.fromhex(h)) print(" RESULT: SIGNATURE VALID") except BadSignatureError: print(" RESULT: SIGNATURE INVALID"); return False print(f"\n[File Integrity] ({len(m['files'])} files)") all_ok = True for fi in m["files"]: p = os.path.join(d, os.path.basename(fi["path"])) if not os.path.exists(p): print(f" MISSING {fi['path']}"); all_ok = False; continue fh = hashlib.sha256(open(p, "rb").read()).hexdigest() sz = os.stat(p).st_size ok = fh == fi["sha256"] and sz == fi["bytes"] tag = "OK" if ok else "FAIL" print(f" {tag} {fi['path']} ({fi['bytes']}b)") if not ok: all_ok = False v = "ALL VERIFIED" if all_ok else "VERIFICATION FAILED" print(f"\n{v}") return all_ok if __name__ == "__main__": if len(sys.argv) > 1 and sys.argv[1] == "--verify-release": d = sys.argv[2] if len(sys.argv) > 2 else "." ok = verify_release(d) else: f = sys.argv[1] if len(sys.argv) > 1 else "test_response.json" ok = verify(f) sys.exit(0 if ok else 1)