Final articles ship as a PDF plus a detached .pdf.sig.json sidecar. The sidecar holds a small manifest (PDF hash, source hash, key IDs, date) signed twice — Ed25519 and ML-DSA-65 — and both signatures must verify. Preprints are unsigned and say so.

Keys

Ed25519
SHA256:ye1WU5RW5PWz2tX6FDdGy1Ke+W+5iCyWSyW3iKfQgqY
ed25519.pub · allowed_signers
ML-DSA-65
272d7b87a76a2822756cc382699f0f2ecede607f57fd478b13c699fe4af6574f
mldsa65.pub.pem

Cross-check the fingerprints against the ones in therepository README before trusting them.

Verify a PDF

Replace SLUG. Needs jq, OpenSSH, and OpenSSL ≥ 3.5 for ML-DSA.

# 1. Fetch the article, its sidecar and the keys
P=SLUG; U=https://woland.statichost.page/blog/$P
curl -sO $U/$P.pdf -O $U/$P.pdf.sig.json
curl -sO https://woland.statichost.page/keys/allowed_signers -O https://woland.statichost.page/keys/mldsa65.pub.pem

# 2. The manifest must name this PDF
[ "$(sha256sum $P.pdf | cut -d' ' -f1)" = "$(jq -r .manifest.sha256 $P.pdf.sig.json)" ] && echo "pdf hash ok"

# 3. Extract the canonical manifest bytes and both signatures
jq -cjS .manifest            $P.pdf.sig.json > manifest.json
jq -r   .signatures.ed25519  $P.pdf.sig.json > manifest.json.sig
jq -r   .signatures.mldsa65  $P.pdf.sig.json | base64 -d > manifest.mldsa65

# 4. Both must pass
ssh-keygen -Y verify -f allowed_signers -I woland@woland.space -n woland-blog \
    -s manifest.json.sig < manifest.json
openssl pkeyutl -verify -pubin -inkey mldsa65.pub.pem -rawin \
    -in manifest.json -sigfile manifest.mldsa65

Fingerprints to compare with the ones above: ssh-keygen -lf allowed_signers andopenssl pkey -pubin -in mldsa65.pub.pem -outform DER | tail -c 1952 | sha256sum.

Or clone the repository and run npm run verify, which does the same checks in JavaScript and additionally confirms the article source hasn't changed since signing.

Why two algorithms

ML-DSA (FIPS 204) is the post-quantum signature; Ed25519 is the classical one. Requiring both follows the European (ANSSI/BSI) transition guidance: a flaw found in the young lattice scheme doesn't void the signature, and neither does a future quantum computer.