cipherpost v2 alpha¶
cipherpost is a command-line tool for handing someone a key, a certificate, or a secret without a server or an account in the middle. Your PKARR keypair is your identity, the Mainline DHT is the meeting point, the payload is end-to-end encrypted, and the recipient publishes a signed receipt so you know it arrived.
On August 1 I tagged v2.0.0-alpha.1. It's an alpha and it breaks the wire format, but the change underneath it is the most interesting design work in the project so far.
The Problem With v1¶
In v1, everything a sender published lived under one key: their public identity. The DHT gives each key a single small record, about 1000 bytes. So a sender could only have one share outstanding at a time, and a recipient's receipts all piled into the same place. Worse, anyone who knew your public key could look up that record and see your receipts. The content was encrypted, but the shape of your activity was not.
Every Share Gets Its Own Key¶
v2 publishes every share, and every receipt, under its own key derived from the parent identity and the share's reference. It is a single-hop stealth derivation: hash the parent public key together with the share reference, and use the result to blind the parent key into a new one. Only someone who knows the share reference can find the record.
The off-the-shelf PKARR library can't sign under a key like that, so cipherpost signs those DHT packets itself and verifies its own signature before publishing. Byte-exact golden vectors pin the derivation in the spec and the tests, so it can't drift.
What that buys:
- Many shares at once. The one-record ceiling is gone. A sender can have as many outstanding shares as they want, and a recipient can publish as many receipts.
- Private receipts. Receipts can no longer be listed from someone's public key. You need the share reference to find one, which is why
cipherpost receiptsnow requires--share-ref. - Less metadata. The receipt is slimmer, and the sender's stated purpose is no longer published in the clear.
- Less code. The old merge-and-republish logic, with its compare-and-swap retry and the race it was guarding against, is gone. About 765 lines net came out.
Proof on the Real DHT¶
Unit tests run against a mock DHT, which is fast and deterministic and proves nothing about the real network. So tagging the release kicked off a cross-identity round trip against the live Mainline DHT: publish a share under one derived key, resolve it from another identity, publish the receipt under a third. It passed in 739 seconds. The evidence file and the CI artifact are both in the repo.
What I Learned¶
The limit I kept working around in v1 was not really a size limit. It was an addressing decision. Once each share had its own address, the size problem, the privacy leak, and the concurrency race all went away together, and the code got smaller. That is usually a sign the earlier design was fighting the medium.
What's Next¶
It is an alpha. v1 and v2 can't talk to each other, because they derive different keys. Before a stable 2.0 I want more real-world handoffs and more eyes on the derivation. If you work with PKARR or Pubky and want to poke at it, the spec and threat model are in the repo.
Links¶
Hand off a secret without handing anyone your metadata.