X-39 Evidencia: hardened offline evidence verifier on ICP (open ZIPspec + JS reference)

Hi all,

Sharing a release of X-39 Evidencia, a proof-of-existence layer for documents that runs its web and verifier from an ICP asset canister.

What it does: you seal a document; the proof is anchored in Bitcoin via OpenTimestamps, optionally gets a qualified RFC 3161 timestamp, and can carry an ML-DSA-87 (FIPS 204) co-signature. The reference verifier then checks an evidence bundle fully offline, without trusting the service: sha256 integrity, cross-field consistency, chat-chain continuity, and per-message Ed25519 signatures anchored in proof.json.

What’s new in this release:

  • Evidence bundles repackaged by macOS (Finder/ditto) now verify cleanly instead of being rejected as an unsupported container.
  • The ZIP container rules are now an open spec, with a JavaScript reference implementation kept in parity with the Python verifier — so the parsing rules themselves are auditable, not just the code.

Where to find it (the forum won’t let me post links yet, so plain text):

  • Web and verifier: asset canister tvkfy-xqaaa-aaaab-qheta-cai, custom domain x39matrix.org, verifier at /verify_bundle.py
  • Code & spec (AGPL-3.0): github.com/x39matrix/x39-Evidencia

It’s a one-person project; feedback and adversarial testing are very welcome.

Update — the reference verifier is now published as a release, with both of its timestamps attached.

github.com/x39matrix/x39-Evidencia/releases/tag/verificador-c03e715e

SHA-256 c03e715e8ec2078aedace0c62dcec6dca10eea21c6e93c5b9e16f7da50398aab

Two independent clocks over that digest:

Bitcoin (OpenTimestamps): block 971415, 2026-10-14. The .ots is in the release. To trust nothing in between, cross-check the attestation block hash against bitcoin-cli getblockhash 971415 on your own node.
Qualified RFC 3161 timestamp: issued by a TSA that the Spanish Trust List registers as qualified. The .tsr, its certificate chain and the local verification record are in the release; the signature verifies offline.

The two rest on different things on purpose. The Bitcoin clock needs trust in no one. The qualified one needs trust in a registered authority, and under eIDAS it carries a presumption of the date and of the integrity of the data — not of the truth of the content. Neither of them requires trusting me. The release notes state the limits, including why fetching the issuer’s root from the issuer is circular and where the independent anchor is.

To be clear about what this is not: there is no external security audit, and no independent reproduction yet. Both are being sought.

If anyone feels like breaking something, the verifier’s strictest work is ZIP container parsing — extra fields, name collisions, encoding. A malformed container must never come back clean. That is the surface I would most like attacked.