File size: 1,937 Bytes
767a051
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
"""Exact TOM canonical seed verification."""
from __future__ import annotations

from dataclasses import dataclass
from pathlib import Path

from .canonical import digest_bytes

CANONICAL_SEED_LENGTH = 244
CANONICAL_SEED_SHA256 = "d1417a3136772c0cf3eddcd4962ce07d42cbf87616f7b5bae09fc652d9b807b5"
CANONICAL_SEED_TEXT = (
    "TOM1[TopologicalOpenModular]|TomKlootwijk|1990-07-10|NL200678942|2026-09-01|"
    "LUTlogp^{Klein,SDF0@Def}(rho,theta,t->;phi,dt,d2,J,v,a,j1)>P1>L2_BST^b>"
    "ASweepCone(T,apex)>Pi[pyrSide,circle,sphere]>support>compatibility>guard>event>"
    "transition>lineage"
)


@dataclass(frozen=True, slots=True)
class SeedIdentity:
    bytes: int
    sha256: str
    text: str

    def as_record(self) -> dict[str, object]:
        return {
            "bytes": self.bytes,
            "sha256": self.sha256,
            "encoding": "ASCII/UTF-8",
            "terminal_line_feed": False,
            "grammar": "TOM-SRS-1.0-COMPACT-SEED",
        }


def verify_seed_bytes(raw: bytes) -> SeedIdentity:
    if not isinstance(raw, bytes):
        raise TypeError("seed must be bytes")
    if raw.endswith((b"\n", b"\r")):
        raise ValueError("canonical TOM seed must not have a terminal line ending")
    try:
        text = raw.decode("ascii")
    except UnicodeDecodeError as exc:
        raise ValueError("canonical TOM seed must contain ASCII characters only") from exc
    if len(raw) != CANONICAL_SEED_LENGTH:
        raise ValueError(f"canonical TOM seed length mismatch: {len(raw)}")
    digest = digest_bytes(raw, prefix=False)
    if digest != CANONICAL_SEED_SHA256:
        raise ValueError(f"canonical TOM seed SHA-256 mismatch: {digest}")
    if text != CANONICAL_SEED_TEXT:
        raise ValueError("canonical TOM seed literal mismatch")
    return SeedIdentity(len(raw), digest, text)


def verify_seed_file(path: str | Path) -> SeedIdentity:
    return verify_seed_bytes(Path(path).read_bytes())