Verify scan record
How the check works
A scan record from protsocials makes three statements: its content (JSON file and PDF) is unchanged, protsocials signed it, and an independent time-stamping authority confirmed that it existed at that time.
Upload the files you get when you download a scan record, or paste their content. The JSON file is enough for the hash. A complete check needs the manifest, the PDF, the signature and the timestamp together. Without the PDF it stays unchecked, and the result says so.
A scan record for one post is checked with its JSON file, its signature and its timestamp. It has no manifest, and its PDF is not signed.
The files are only read. Nothing is stored, and you need no account.
The signature is an advanced technical seal by protsocials, neither a qualified electronic signature nor a qualified electronic time stamp under the eIDAS Regulation.
The scan record's files
The manifest's layout
The manifest consists of exactly these bytes: JSON in UTF-8, no whitespace and no trailing newline, with the keys in this order. The timestamp and the signature refer to these bytes.
{"manifest":1,"record":"<id>","json":"<sha256 of the JSON file>","pdf":"<sha256 of the PDF>"}
Public keys
The keys protsocials signs with are published at https://protsocials.com/.well-known/protsocials-record-keys.json, with the time each key began and stopped.
Check it yourself with openssl
Every check can also be run on your own computer, without trusting this page. You need the scan record’s files (R.json, R.pdf, R.manifest.json, R.signature.json and R.tsr) and sha256sum, openssl, curl and jq. Replace “R” with the name of your files.
A scan record for one post has no manifest: in steps 2 and 3, use R.json instead of R.manifest.json.
1. The content is unchanged
The two values must be the “json” and “pdf” fields of the manifest.
sha256sum R.json R.pdf2. protsocials signed it
The commands fetch the published key for the id in R.signature.json and check the signature over the manifest’s bytes. If it holds, you see “Signature Verified Successfully”.
KEYS='https://protsocials.com/.well-known/protsocials-record-keys.json' KID=$(jq -r .kid R.signature.json) KID_PUB=$(curl -s "$KEYS" | jq -r --arg kid "$KID" '.keys[] | select(.kid == $kid) | .publicKey') printf '%s' "$KID_PUB" | tr '_-' '/+' | base64 -d > key.raw # raw 32 bytes ( printf '\x30\x2a\x30\x05\x06\x03\x2b\x65\x70\x03\x21\x00'; cat key.raw ) \ | openssl pkey -inform DER -pubin -out key.pem jq -r .signature R.signature.json | tr '_-' '/+' | base64 -d 2>/dev/null > sig.bin # 64 bytes openssl pkeyutl -verify -pubin -inkey key.pem -rawin -in R.manifest.json -sigfile sig.bin # Signature Verified Successfully3. An independent timestamp authority confirmed the time
root.pem is the timestamp authority’s root certificate. Its operator publishes it; check its fingerprint against a second source. If the timestamp holds, you see “Verification: OK”.
openssl ts -verify -in R.tsr -data R.manifest.json -CAfile root.pem # Verification: OK