A receipt is signed with Ed25519 and is asked to show who decided what for
years. The receipts of a log already commit to one another by hash, so the
content id of the last one fixes every byte behind it. A log seal signs
that id, and how many receipts it covers, twice over the same bytes:
Ed25519 beside ML-DSA-65, as the composite id-MLDSA65-Ed25519-SHA512 the
family's signed records already use. Receipts keep their bytes.
- extensions/log-seal.md: the record, the signing bytes, the keys, and the
reading in five ordered steps under two choices: whether receipts are
held to their own signatures or to the seal alone, and whether receipts
no seal covers are reported or refused. What it does not give is stated.
- jcp-logseal: seal_log, read_seal, verify_sealed_log. A history written
under the steward's own Ed25519 key verifies receipt by receipt and is
refused against the seal; a log cut short of a seal, which a hash chain
alone cannot show, is refused; seals chain, so none can be dropped.
- jcp-receipt: verify_chain follows a log's chain with no signature
consulted. An envelope with bytes after its signature is now refused: it
verified, and gave one receipt two content ids.
- Conformance C33, and conformance/v1/log_seal.json: three logs, eleven
seals, twenty-three cases, every refusal code exercised.
- conformance/verify_seal.py decides every case with its own encoding,
hashing and Ed25519 and the family's second ML-DSA-65, and under
--selftest removes each of its rules and requires a case to notice.
- Both implementations verify the test case the composite's own
specification publishes for this suite. Five faults seeded into the
reference are each caught by the pack.
Co-Authored-By: Claude <[email protected]>