How it works
Pitch the tree. Stamp the tip.
Five moving parts, each small enough to check by hand. Nothing here needs you to trust TIPISTAMP.
Terms + parties frozen into one canonical form.
SHA-256 of that statement — 32 bytes.
Each party signs the fingerprint with their own key.
Completed agreements roll into a Merkle root.
The root is published into a Bitcoin block.
The canonical statement
Both parties must be bound to exactly the same bytes. TIPISTAMP serialises the terms, the
named parties, and the effective date into one deterministic string — whitespace, key order, and encoding all fixed.
That string is the statement. Its SHA-256 is the statement_hash.
- Why hash it?
- So the thing being signed is tiny and fixed. Change one character of the terms and the hash is unrecognisably different — every signature over the old hash instantly fails.
Bilateral signatures (ES256)
Each party holds an ECDSA P-256 key pair. The private key is generated in the browser with WebCrypto and never sent to the server — only the public key is registered. Signing produces a 64-byte signature over the 32-byte statement hash.
An agreement is complete only when every named party has a valid signature on file. Until then it sits pending. A first-time signer’s key is recorded on their first signature (trust on first use) and reused from then on.
The tip, and the stamp
Completed agreements are the leaves of a Merkle tree. Its root — the tip — depends on every leaf. TIPISTAMP submits that single 32-byte root to OpenTimestamps, which batches it into a Bitcoin transaction. Once the block is mined, the tip’s existence is fixed at that block’s time for everyone, forever. No one, TIPISTAMP included, can make Bitcoin say otherwise.
Verifying, offline
Anyone you hand a bundle to can check it with no account and no connection to us:
- Recompute the statement hash from the terms — it must match.
- Check both signatures against the registered public keys.
- Walk the Merkle path — it must reproduce the tip.
- Confirm the OpenTimestamps proof against a Bitcoin block header.
agreement-verify.php does all four and exits 0 on success. The block’s
timestamp is the date the agreement provably existed by.