tools/verify_token_crypto.py — locks in §3:
- Opportunistic Token encrypt/decrypt round-trip with full
ephemeral_pub(32) || iv(16) || aes(...) || hmac(32) layout check.
- HKDF salt = recipient.identity_hash verified by re-deriving
the key by hand and confirming decrypt succeeds.
- Link-derived Token form (no eph_pub prefix) round-trip.
- HMAC-then-AES order proven by tampering each region: HMAC
mismatch raises before AES decrypt.
- PKCS#7 padding boundaries (1B and 16B plaintexts).
tools/verify_announce_roundtrip.py — locks in §4 + §4.5:
- Build via upstream Destination.announce(send=False).
- Body layout walk with context_flag branching for the optional
ratchet slot.
- signed_data reconstruction per §4.2 with empty-bytes-not-absent
ratchet rule.
- dest_hash recompute per §1.2.
- random_hash[5:10] is a recent unix_seconds timestamp per §4.1
(corrected — confirms upstream emits the timestamp half).
- Upstream validate_announce accepts.
- Tamper detection: bit-flips in signature, public_key, name_hash,
random_hash, app_data are all rejected.
tools/verify_lxmf_opportunistic.py — locks in §5.1, §5.2, §5.5, §5.6
plus §3 layered correctly:
- Two identities (Alice, Bob) with mutual discovery.
- LXMessage build with title, content, fields.
- Body layout: dest(16) || src(16) || sig(64) || msgpack.
- Opportunistic-form strip of leading dest_hash before encryption.
- Encrypt to Bob via Token, decrypt as Bob, byte-identical
round-trip.
- Re-prepend dest_hash and run unpack_from_bytes; confirms
signature_validated=True and title/content/fields preserved.
All three pass against RNS 1.2.0 / LXMF 0.9.6.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|---|---|---|
| .. | ||
| README.md | ||
| regen_identities.py | ||
| verify_announce_app_data.py | ||
| verify_announce_roundtrip.py | ||
| verify_destination_hash.py | ||
| verify_lxmf_opportunistic.py | ||
| verify_packet_header.py | ||
| verify_path_request.py | ||
| verify_token_crypto.py | ||
Verifier scripts
Self-contained Python scripts that test claims in ../SPEC.md against the upstream RNS / LXMF Python stack.
Conventions
- Each script verifies one claim or one related cluster of claims.
- Exit code 0 on PASS, non-zero on FAIL.
- Print a one-line PASS/FAIL summary plus a unified diff or hex dump on mismatch.
- Reference the SPEC.md section the script verifies in a docstring at the top.
Required environment
pip install rns lxmf
The scripts read RNS.__version__ at startup and print it in their output so a future reader can tell which RNS version a verification ran against.
Status
Populated against RNS 1.2.0 / LXMF 0.9.6:
| Script | Verifies SPEC.md section | Status |
|---|---|---|
verify_destination_hash.py |
§1.1, §1.2, §1.3 — identity composition, dest_hash = SHA256(name_hash || identity_hash)[:16], on-disk private-key round-trip via to_file/from_file |
✅ |
verify_packet_header.py |
§2.1, §2.2, §2.3 — flag byte layout, HEADER_1/HEADER_2 form, originator HEADER_1→HEADER_2 conversion via upstream Transport.outbound |
✅ |
verify_announce_app_data.py |
§4.3 — LXMF announce app_data 2-element form, parser tolerance | ✅ |
verify_path_request.py |
§1.2 well-known hashes, §7.1 LXMF path-preamble gating | ✅ |
regen_identities.py |
regenerates test-vectors/identities.json |
✅ |
verify_announce_roundtrip.py |
§4 — announce build matches upstream Identity().announce() bytes |
⏳ |
verify_token_crypto.py |
§3 — Token encrypt/decrypt against upstream RNS.Cryptography.Token |
⏳ |
verify_lxmf_opportunistic.py |
§5.1, §5.5 — opportunistic LXMF body bytes match upstream | ⏳ |
verify_link_handshake.py |
§6 — LINKREQUEST + LRPROOF + session key match upstream | ⏳ |
verify_msgpack_quirk.py |
§9.3 — encoding name as bytes vs str affects upstream parsing | ⏳ |
See ../agent.md §5 and ../todo.md for the remaining priority order.