pith seal
Documentation
Seal from the command line
The sealer is one Python file with no dependencies. It hashes on your machine and sends only the root. With a salt key, each file's salt is derived from the key, so you never need to store a seal file: check out the same commit years later, run rebuild with the key, and reveal. Sealing from the command line needs a Seal Pro API key, from your account.
curl -sSfO https://pith.science/seal/pith_seal.py python3 pith_seal.py keygen > seal.key # keep this secret; it rebuilds every seal export PITH_SEAL_KEY=pseal_... # your API key python3 pith_seal.py seal ./my-project --salt-key-file seal.key --label "draft 3"
Seal every push
In GitHub Actions, add your API key and salt key as repository secrets:
name: seal
on: push
jobs:
seal:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: curl -sSf -o "$RUNNER_TEMP/pith_seal.py" https://pith.science/seal/pith_seal.py
- run: python3 "$RUNNER_TEMP/pith_seal.py" seal . --no-kit --label "${{ github.repository }}@${{ github.sha }}"
env:
PITH_SEAL_KEY: ${{ secrets.PITH_SEAL_KEY }}
PITH_SEAL_SALT_KEY: ${{ secrets.PITH_SEAL_SALT_KEY }}
Reveal from a sealed commit
Make a clean checkout of the commit, rebuild its seal file with the salt key, then reveal one file or all of them. Revealing every file makes the receipt say that nothing in the seal stays hidden, which is what a prediction or a preregistered plan needs.
python3 pith_seal.py rebuild <seal id> . --salt-key-file seal.key python3 pith_seal.py reveal .pith-seal/pith-seal-<id>.json path/to/file --title "..." --doi 10.1234/abc python3 pith_seal.py reveal .pith-seal/pith-seal-<id>.json --all
With --attest, the receipt shows that the Seal Pro account revealing the file is the account Pith recorded as making the seal. It shows which account made the seal, not who wrote the work.
Permanent copies
When you seal in the browser, the page can also store an encrypted copy of the files and their seal file on Arweave, a blockchain built to keep data permanently. Neither you nor Pith hosts it. One set of 24 recovery words finds the copy and opens it at the recovery page from any computer, even if your devices are gone and Pith with them. The copy is public on Arweave, which is how it survives, but it is encrypted in your browser with a 256-bit key made from the words, and Pith never sees them.
If something happens to you, three people you trust can each hold a card: any two of them together open the copy, and one card alone opens nothing. A timed-release capsule stored on Arweave opens for everyone on the date you choose, with nobody needing to act.
Copies up to 100 KB are stored free. Seal Pro includes larger ones, up to 10 MB each and 50 MB a month: Pith's storage account pays, and the copy is still signed by the key made from your recovery words, so it stays yours and Pith can neither open it nor take it down.
Timed release
A capsule is a copy of your sealed files locked with drand's public time-lock until a moment you choose. drand is a network of independent organizations that signs a new value every three seconds; the signature for your moment is the key, and nobody holds it until then. If drand stopped before your moment, the capsule would never open, so keep your own copy of the files. The lock trusts that a threshold of drand's members won't sign a moment early, and it uses elliptic-curve cryptography that a large quantum computer could break. The seal itself doesn't depend on drand.
API
POST /api/v1/seals {"root": hex, "label"?} Bearer key or Pro session records it to your account
GET /api/v1/seals Bearer key: your seals
GET /api/v1/seals/{id} the receipt as JSON, including all_revealed
POST /api/v1/seals/{id}/reveals {"file_sha256", "salt", "path", "name"?, "title"?, "url"?, "doi"?, "attest"?}
GET /seal/{id}/statement.txt the anchored statement; .ots and .{digicert,freetsa}.tsr hold its proofs