| 1 | """ |
| 2 | test_manifest_p256_parse_unit |
| 3 | ============================= |
| 4 | Regression test for the cross-language HW-P256 manifest parse bug. |
| 5 | |
| 6 | Previously the Python manifest parser hard-rejected `p256_pub` as an unknown |
| 7 | recipient field, which made every Rust-sealed OSGT-HW-P256-v1 container |
| 8 | unopenable and uninspectable by Python. Rust is the forward canonical |
| 9 | implementation; Python keeps parse and inspect parity during the transition |
| 10 | but does not implement the HW-P256 seal/open crypto path. Canonicalization |
| 11 | of the field set is covered separately by the JCS-unification work. |
| 12 | """ |
| 13 | |
| 14 | from __future__ import annotations |
| 15 | |
| 16 | import json |
| 17 | import sys |
| 18 | from pathlib import Path |
| 19 | |
| 20 | ROOT = Path(__file__).resolve().parent.parent |
| 21 | sys.path.insert(0, str(ROOT)) |
| 22 | |
| 23 | from oversight_core.manifest import Manifest, Recipient |
| 24 | |
| 25 | |
| 26 | def test_recipient_has_p256_pub_field(): |
| 27 | r = Recipient(recipient_id="alice", x25519_pub="00" * 32, p256_pub="ab" * 32) |
| 28 | assert r.p256_pub == "ab" * 32 |
| 29 | |
| 30 | |
| 31 | def test_p256_pub_defaults_none_so_classic_manifests_unchanged(): |
| 32 | r = Recipient(recipient_id="alice", x25519_pub="00" * 32) |
| 33 | assert r.p256_pub is None |
| 34 | |
| 35 | |
| 36 | def test_manifest_from_json_accepts_p256_pub_recipient(): |
| 37 | payload = { |
| 38 | "file_id": "00000000-0000-4000-8000-000000000000", |
| 39 | "issued_at": 1700000000, |
| 40 | "suite": "OSGT-HW-P256-v1", |
| 41 | "recipient": { |
| 42 | "recipient_id": "alice", |
| 43 | "x25519_pub": "00" * 32, |
| 44 | "p256_pub": "cd" * 32, |
| 45 | }, |
| 46 | } |
| 47 | m = Manifest.from_json(json.dumps(payload, sort_keys=True).encode("utf-8")) |
| 48 | assert m.suite == "OSGT-HW-P256-v1" |
| 49 | assert m.recipient is not None |
| 50 | assert m.recipient.p256_pub == "cd" * 32 |
| 51 | |
| 52 | |
| 53 | def test_classic_manifest_canonical_bytes_unchanged_by_new_field(): |
| 54 | r = Recipient(recipient_id="alice", x25519_pub="00" * 32) |
| 55 | m = Manifest( |
| 56 | file_id="00000000-0000-4000-8000-000000000000", |
| 57 | issued_at=1700000000, |
| 58 | recipient=r, |
| 59 | ) |
| 60 | canon = m.canonical_bytes().decode("utf-8") |
| 61 | assert "p256_pub" not in canon |