From f186b71ca51e83837db60de13322394bb5e6d348 Mon Sep 17 00:00:00 2001 From: murilo ijanc Date: Tue, 24 Mar 2026 21:41:06 -0300 Subject: Initial commit Import existing tesseras.net website content. --- news/phase4-wasm-browser-verification/index.html | 192 +++++++++++++++++++++ .../phase4-wasm-browser-verification/index.html.gz | Bin 0 -> 4765 bytes 2 files changed, 192 insertions(+) create mode 100644 news/phase4-wasm-browser-verification/index.html create mode 100644 news/phase4-wasm-browser-verification/index.html.gz (limited to 'news/phase4-wasm-browser-verification') diff --git a/news/phase4-wasm-browser-verification/index.html b/news/phase4-wasm-browser-verification/index.html new file mode 100644 index 0000000..571e094 --- /dev/null +++ b/news/phase4-wasm-browser-verification/index.html @@ -0,0 +1,192 @@ + + + + + + Phase 4: Verify Without Installing Anything — Tesseras + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ + + Tesseras + +

+ + +
+ +
+ +
+

Phase 4: Verify Without Installing Anything

+

2026-02-15

+

Trust shouldn't require installing software. If someone sends you a tessera — a +bundle of preserved memories — you should be able to verify it's genuine and +unmodified without downloading an app, creating an account, or trusting a +server. That's what tesseras-wasm delivers: drag a tessera archive into a web +page, and cryptographic verification happens entirely in your browser.

+

What was built

+

tesseras-wasm — A Rust crate that compiles to WebAssembly via wasm-pack, +exposing four stateless functions to JavaScript. The crate depends on +tesseras-core for manifest parsing and calls cryptographic primitives directly +(blake3, ed25519-dalek) rather than depending on tesseras-crypto, which pulls +in C-based post-quantum libraries that don't compile to +wasm32-unknown-unknown.

+

parse_manifest takes raw MANIFEST bytes (UTF-8 plain text, not MessagePack), +delegates to tesseras_core::manifest::Manifest::parse(), and returns a JSON +string with the creator's Ed25519 public key, signature file paths, and a list +of files with their expected BLAKE3 hashes, sizes, and MIME types. Internal +structs (ManifestJson, CreatorPubkey, SignatureFiles, FileEntry) are +serialized with serde_json. The ML-DSA public key and signature file fields are +present in the JSON contract but set to null — ready for when post-quantum +signing is implemented on the native side.

+

hash_blake3 computes a BLAKE3 hash of arbitrary bytes and returns a +64-character hex string. It's called once per file in the tessera to verify +integrity against the MANIFEST.

+

verify_ed25519 takes a message, a 64-byte signature, and a 32-byte public key, +constructs an ed25519_dalek::VerifyingKey, and returns whether the signature +is valid. Length validation returns descriptive errors ("Ed25519 public key must +be 32 bytes") rather than panicking.

+

verify_ml_dsa is a stub that returns an error explaining ML-DSA verification +is not yet available. This is deliberate: the ml-dsa crate on crates.io is +v0.1.0-rc.7 (pre-release), and tesseras-crypto uses pqcrypto-dilithium +(C-based CRYSTALS-Dilithium) which is byte-incompatible with FIPS 204 ML-DSA. +Both sides need to use the same pure Rust implementation before +cross-verification works. Ed25519 verification is sufficient — every tessera is +Ed25519-signed.

+

All four functions use a two-layer pattern for testability: inner functions +return Result<T, String> and are tested natively, while thin #[wasm_bindgen] +wrappers convert errors to JsError. This avoids JsError::new() panicking on +non-WASM targets during testing.

+

The compiled WASM binary is 109 KB raw and 44 KB gzipped — well under the 200 KB +budget. wasm-opt applies -Oz optimization after wasm-pack builds with +opt-level = "z", LTO, and single codegen unit.

+

@tesseras/verify — A TypeScript npm package (crates/tesseras-wasm/js/) +that orchestrates browser-side verification. The public API is a single +function:

+
async function verifyTessera(
+  archive: Uint8Array,
+  onProgress?: (current: number, total: number, file: string) => void
+): Promise<VerificationResult>
+
+

The VerificationResult type provides everything a UI needs: overall validity, +tessera hash, creator public keys, signature status (valid/invalid/missing for +both Ed25519 and ML-DSA), per-file integrity results with expected and actual +hashes, a list of unexpected files not in the MANIFEST, and an errors array.

+

Archive unpacking (unpack.ts) handles three formats: gzip-compressed tar +(detected by \x1f\x8b magic bytes, decompressed with fflate then parsed as +tar), ZIP (PK\x03\x04 magic, unpacked with fflate's unzipSync), and raw tar +(ustar at offset 257). A normalizePath function strips the leading +tessera-<hash>/ prefix so internal paths match MANIFEST entries.

+

Verification runs in a Web Worker (worker.ts) to keep the UI thread +responsive. The worker initializes the WASM module, unpacks the archive, parses +the MANIFEST, verifies the Ed25519 signature against the creator's public key, +then hashes each file with BLAKE3 and compares against expected values. Progress +messages stream back to the main thread after each file. If any signature is +invalid, verification stops early without hashing files — failing fast on the +most critical check.

+

The archive is transferred to the worker with zero-copy +(worker.postMessage({ type: "verify", archive }, [archive.buffer])) to avoid +duplicating potentially large tessera files in memory.

+

Build pipeline — Three new justfile targets: wasm-build runs wasm-pack +with --target web --release and optimizes with wasm-opt; wasm-size reports +raw and gzipped binary size; test-wasm runs the native test suite.

+

Tests — 9 native unit tests cover BLAKE3 hashing (empty input, known value), +Ed25519 verification (valid signature, invalid signature, wrong key, bad key +length), and MANIFEST parsing (valid manifest, invalid UTF-8, garbage input). 3 +WASM integration tests run in headless Chrome via +wasm-pack test --headless --chrome, verifying that hash_blake3, +verify_ed25519, and parse_manifest work correctly when compiled to +wasm32-unknown-unknown.

+

Architecture decisions

+ +

What comes next

+ +

Verification no longer requires trust in software. A tessera archive dropped +into a browser is verified with the same cryptographic rigor as the CLI — same +BLAKE3 hashes, same Ed25519 signatures, same MANIFEST parser. The difference is +that now anyone can do it.

+ +
+ +
+ + + + diff --git a/news/phase4-wasm-browser-verification/index.html.gz b/news/phase4-wasm-browser-verification/index.html.gz new file mode 100644 index 0000000..41c46ac Binary files /dev/null and b/news/phase4-wasm-browser-verification/index.html.gz differ -- cgit v1.2.3