#!/usr/bin/env python3
"""
verify_seal.py — check an opened entry against the published Sealed Register.

Sealed Register of Recorded Inventions, Andreas Ehstand, 23 September 2026
Open record: https://doi.org/10.5281/zenodo.22909343

WHAT THIS DOES
--------------
Each of the 803 entries in the register is published as a SHA-256 fingerprint only —
number, function group, fingerprint. No content.

When the holder opens one entry, they disclose its eight fields. This program
recomputes the fingerprint from those fields and compares it to the published one.
If they match, that entry existed in exactly that form on the sealing date.

No key, no service, no permission and no network access are required.
This file is the whole verifier. Read it; it is twenty lines of logic.

HOW THE FINGERPRINT IS FORMED
-----------------------------
Eight fields in fixed order:
    1 number
    2 name
    3 family
    4 one-sentence description
    5 class
    6 prior-art grading
    7 short code
    8 source references
followed by a ninth element, the archive date: 2026-09-21

Joined with the byte 0x1F (ASCII unit separator), encoded UTF-8, hashed SHA-256.

USAGE
-----
    python verify_seal.py --selftest
    python verify_seal.py opened_entry.json SIEGEL_REGISTER_OEFFENTLICH.csv

where opened_entry.json is:
    {"nr": 1, "name": "...", "familie": "...", "satz": "...",
     "geld_klasse": "...", "erstheit": "...", "e_code": "...",
     "fundstellen": "...", "stand": "2026-09-21"}
"""
import csv
import hashlib
import json
import sys

SEPARATOR = "\x1f"
FIELDS = ["nr", "name", "familie", "satz", "geld_klasse",
          "erstheit", "e_code", "fundstellen", "stand"]

# SHA-256 over all 803 entry fingerprints, ascending entry order, newline-separated.
ROOT = "41f9f070f92476b668c54ecd350459b2d094c7365cda4e338f4ad80d0a134f5f"


def fingerprint(entry):
    """Return the SHA-256 fingerprint of one opened entry."""
    canonical = SEPARATOR.join(str(entry[f]) for f in FIELDS)
    return hashlib.sha256(canonical.encode("utf-8")).hexdigest()


def root_fingerprint(fingerprints_in_entry_order):
    """Return the SHA-256 over all entry fingerprints, newline-separated."""
    return hashlib.sha256("\n".join(fingerprints_in_entry_order).encode()).hexdigest()


def selftest():
    """Demonstrate the computation on an invented entry. Reveals nothing real."""
    demo = {
        "nr": 0,
        "name": "Example Entry (not a real invention)",
        "familie": "F00",
        "satz": "This entry is invented solely to demonstrate the computation.",
        "geld_klasse": "X",
        "erstheit": "demonstration only",
        "e_code": "demo",
        "fundstellen": "none",
        "stand": "2026-09-21",
    }
    fp = fingerprint(demo)
    print("Self-test — invented entry, no real content disclosed")
    print("  canonical form (separator shown as \\x1f):")
    print("    " + SEPARATOR.join(str(demo[f]) for f in FIELDS).replace(SEPARATOR, "\\x1f"))
    print("  SHA-256: " + fp)
    print("\n  Recompute it yourself in one line:")
    print("    python -c \"import hashlib;print(hashlib.sha256('\\x1f'.join([...]).encode()).hexdigest())\"")
    print("\n  If your result equals the line above, this program works as described.")
    return 0


def main(argv):
    if "--selftest" in argv or len(argv) < 3:
        return selftest()

    entry = json.load(open(argv[1], encoding="utf-8"))
    missing = [f for f in FIELDS if f not in entry]
    if missing:
        print("Entry is incomplete. Missing fields:", ", ".join(missing))
        return 2

    computed = fingerprint(entry)

    register = {}
    with open(argv[2], encoding="utf-8") as fh:
        for row in csv.DictReader(fh):
            register[str(row["entry_no"])] = row["sha256"]

    published = register.get(str(entry["nr"]))
    print("Entry number : %s" % entry["nr"])
    print("Computed     : %s" % computed)
    print("Published    : %s" % (published or "(entry number not in register)"))
    print()
    if published is None:
        print("RESULT: entry number is not in this register.")
        return 3
    if computed == published:
        print("RESULT: MATCH. This entry existed in exactly this form on the sealing date.")
        return 0
    print("RESULT: NO MATCH. Either the disclosed fields differ from the sealed ones,")
    print("        or the entry has been altered since sealing.")
    return 1


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