Standalone verification tool for ArchivioMD and ArchivioID cryptographic post signing
Project description
archiviomd-verify
Standalone verification tool for ArchivioMD and ArchivioID — two WordPress plugins for cryptographic document signing.
Zero WordPress dependency. Given any published post URL the tool fetches the plugin's public REST endpoint and verifies every cryptographic layer locally, printing a pass/fail result for each one.
Requirements
- Python 3.8 or later
- Internet access to the site being verified (and to Rekor / Cloudflare DoH for transparency log and DANE checks)
Check your Python version:
python3 --version
Installation
1. Clone or unzip
Place archiviomd-verify.py, archiviomd-verify.html, and requirements.txt in any directory.
2. Install Python dependencies
pip install -r requirements.txt
This installs cryptography, which enables offline Ed25519, ECDSA P-256, and RSA verification. Everything else is Python stdlib.
For SLH-DSA (post-quantum, NIST FIPS 205) offline verification, also install:
pip install pyspx
3. Install runtime binaries (optional but recommended)
| Binary | Purpose | Install |
|---|---|---|
| openssl | CMS/PKCS#7 and RFC 3161 timestamp offline verify | apt install openssl / brew install openssl |
| gpg | OpenPGP (ArchivioID) offline verify | apt install gnupg / brew install gnupg / Gpg4win on Windows |
Run python3 archiviomd-verify.py --verbose https://example.com/post to see which binaries are detected.
Usage
Verify a post
python3 archiviomd-verify.py https://example.com/my-signed-post
Verify with an explicit Ed25519 public key
python3 archiviomd-verify.py https://example.com/post --pubkey <64-hex-chars>
Use this when the public key is not auto-discoverable from the site's .well-known/ endpoint.
Inspect a Rekor transparency log entry
python3 archiviomd-verify.py --rekor 12345678
Verify an RFC 3161 timestamp file
python3 archiviomd-verify.py --tsr response.tsr --tsq request.tsq
Provide --tsa-cert-url if the TSA certificate is not bundled in your system CA store.
Check DANE DNS records for a domain
python3 archiviomd-verify.py --dane example.com
List all ArchivioID PGP keys registered on a site
python3 archiviomd-verify.py --pgp-keys https://example.com
Inspect ArchivioID PGP signatures for a specific post
python3 archiviomd-verify.py --pgp-keys https://example.com --pgp-post 42
Verbose mode — show dependency status first
python3 archiviomd-verify.py --verbose https://example.com/post
Skip TLS certificate verification (staging / self-signed certs)
python3 archiviomd-verify.py --no-verify-ssl https://staging.example.com/post
Warning: Only use
--no-verify-sslon networks you control. It disables all TLS certificate validation.
What gets checked
| # | Layer | Offline? | Requires |
|---|---|---|---|
| 1 | Content hash (SHA-256/512/etc) | ✓ (non-HMAC) | stdlib |
| 2 | Ed25519 bare + DSSE envelope | ✓ | cryptography |
| 3 | SLH-DSA (NIST FIPS 205) | ✓ | pyspx |
| 4 | ECDSA P-256 DSSE | ✓ | cryptography |
| 5 | RSA PSS / PKCS#1v15 | ✓ | cryptography |
| 6 | CMS / PKCS#7 detached sig | ✓ | openssl binary |
| 7 | JSON-LD / W3C Data Integrity | server-side | — |
| 8 | Rekor transparency log | ✓ (inclusion proof) | internet |
| 9 | RFC 3161 trusted timestamp | ✓ | openssl binary |
| 10 | DANE DNS TXT + TLSA | ✓ | internet (DoH) |
| 11 | OpenPGP (ArchivioID bolt-on) | ✓ (if gpg present) | gpg binary |
Output and exit codes
Each section prints one of:
✓— check passed✗— check failed⚠— warning or missing optional dependency·— informational
Exit code 0 = all performed checks passed.
Exit code 1 = one or more checks failed.
This makes the tool safe to use in CI/CD pipelines:
# GitHub Actions example
- name: Verify post integrity
run: python3 archiviomd-verify.py https://example.com/post
# Shell script example
python3 archiviomd-verify.py https://example.com/post || exit 1
Browser verifier
Open archiviomd-verify.html in any modern browser. It performs client-side verification using the Web Crypto API and requires no installation. Supports layers 1–10 (Ed25519 DSSE, ECDSA P-256 DSSE, content hash, Rekor, RFC 3161 instructions, DANE, JSON-LD).
Layers that require native binaries (SLH-DSA offline, RSA offline, CMS/PKCS#7, OpenPGP) are noted in the UI with a prompt to use the Python CLI.
Notes on HMAC mode
If the site uses HMAC content hashing, offline verification of the content hash requires the ARCHIVIOMD_HMAC_KEY secret, which is never published. The tool will report the server-verified status only.
Verification file format
ArchivioMD attaches a downloadable verification file (JSON) to each signed post — typically accessible via a badge or download link on the post. The CLI references this file in several places. Its structure is:
{
"post_id": 42,
"verification_data": {
"content_hash": {
"algorithm": "sha256",
"hash": "abcdef..."
},
"ed25519": {
"signature_hex": "...",
"public_key_url": "https://example.com/.well-known/ed25519-pubkey.txt"
},
"rsa": {
"signature_hex": "...",
"scheme": "rsa-pss-sha256"
},
"cms": {
"signature_b64": "..."
},
"rfc3161": {
"tsr_url": "https://example.com/wp-content/uploads/archiviomd/42.tsr",
"tsq_url": "https://example.com/wp-content/uploads/archiviomd/42.tsq"
}
}
}
When verifying manually with openssl:
# CMS / PKCS#7
echo "<signature_b64 value>" | base64 -d > sig.der
openssl cms -verify -inform DER -in sig.der -content message.bin -noverify
# RSA (PSS)
echo "<signature_hex value>" | xxd -r -p > sig.der
openssl dgst -sha256 -verify rsa-pubkey.pem -signature sig.der message.bin
# RFC 3161
openssl ts -verify -in 42.tsr -queryfile 42.tsq -CAfile /etc/ssl/certs/ca-certificates.crt
Reproducible installs and version pinning
requirements.txt pins cryptography to a tested range (>=41.0.0,<47). For CI environments or any situation requiring exact reproducibility, use the lock file instead:
pip install -r requirements-lock.txt
To regenerate the lock file after updating requirements.txt:
pip install -r requirements.txt
pip freeze > requirements-lock.txt
For hash-verified installs (maximum supply-chain security), use pip-tools:
pip install pip-tools
pip-compile --generate-hashes requirements.txt -o requirements-lock.txt
pip install --require-hashes -r requirements-lock.txt
RFC 3161 timestamp — what it proves and what it doesn't
When the tool reports a timestamp as VALID, it means:
- A trusted third-party TSA (timestamp authority) cryptographically signed a hash of the content at the recorded time
- The content hash existed before that timestamp
- The TSA's signature has not been tampered with
It does not mean:
- The content itself is authentic or unmodified since then
- The author is who they claim to be
- The content hasn't been replaced (the hash in the TSR must be cross-checked against the content hash above it in the output)
For compliance or legal use, the RFC 3161 timestamp is evidence of prior existence at a specific time, not a guarantee of content integrity on its own. Treat it as one layer in a chain — the content hash, the signature, and the timestamp together form the complete proof.
Browser verifier — CORS dependency
The HTML verifier (archiviomd-verify.html) makes cross-origin fetch requests to the site being verified. This works when:
- The WordPress site sends permissive
Access-Control-Allow-OriginCORS headers on its REST endpoints (ArchivioMD enables this by default) - The HTML file is opened locally (
file://) or served from an allowed origin
It will fail silently or show a CORS error when:
- A WAF (Cloudflare, Sucuri, Wordfence, etc.) strips CORS headers
- A WordPress security plugin blocks REST API access to unauthenticated requests
- The site is behind HTTP Basic Auth or an IP allowlist
If you see a CORS error, use the Python CLI instead — it runs as a normal HTTP client and is not subject to browser CORS restrictions:
python3 archiviomd-verify.py https://example.com/post
Platform notes
Windows: ANSI color output requires Windows 10 version 1903 or later with a modern terminal (Windows Terminal, VS Code terminal). On older systems output renders in plain text without color.
macOS: openssl installed via Homebrew may shadow the system LibreSSL. Either works for the tool's purposes.
Linux: All features work with standard package manager installs.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file archiviomd_verify-1.0.4.tar.gz.
File metadata
- Download URL: archiviomd_verify-1.0.4.tar.gz
- Upload date:
- Size: 23.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b1566f55d98f84538e04e2b5327f1628cdf4c05b0ab953b11349a4eedea65dbb
|
|
| MD5 |
e3762eb02daaffa9d1ae3e6faf858c4c
|
|
| BLAKE2b-256 |
d0e0c39d4b360a509e643d606be5efb9a8c53b85ddab36c58495505f2198f048
|
Provenance
The following attestation bundles were made for archiviomd_verify-1.0.4.tar.gz:
Publisher:
python-publish.yml on MountainViewProvisions/archiviomd-verify
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
archiviomd_verify-1.0.4.tar.gz -
Subject digest:
b1566f55d98f84538e04e2b5327f1628cdf4c05b0ab953b11349a4eedea65dbb - Sigstore transparency entry: 1089602720
- Sigstore integration time:
-
Permalink:
MountainViewProvisions/archiviomd-verify@1674ae528ed6cb5918ce678811b6b1238c654f2e -
Branch / Tag:
refs/tags/v1.0.4 - Owner: https://github.com/MountainViewProvisions
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@1674ae528ed6cb5918ce678811b6b1238c654f2e -
Trigger Event:
push
-
Statement type:
File details
Details for the file archiviomd_verify-1.0.4-py3-none-any.whl.
File metadata
- Download URL: archiviomd_verify-1.0.4-py3-none-any.whl
- Upload date:
- Size: 20.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dd30c34a08cda3c71f92efa12c66731cbb1af4ec2ad44dea17389e46c1870c88
|
|
| MD5 |
c4bdabe7ef714576a400ff524bdfa5e2
|
|
| BLAKE2b-256 |
268ac2b4faaa721eea385ac98cdbbad963dd3d10b14a471292692f6c6ef208bd
|
Provenance
The following attestation bundles were made for archiviomd_verify-1.0.4-py3-none-any.whl:
Publisher:
python-publish.yml on MountainViewProvisions/archiviomd-verify
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
archiviomd_verify-1.0.4-py3-none-any.whl -
Subject digest:
dd30c34a08cda3c71f92efa12c66731cbb1af4ec2ad44dea17389e46c1870c88 - Sigstore transparency entry: 1089602774
- Sigstore integration time:
-
Permalink:
MountainViewProvisions/archiviomd-verify@1674ae528ed6cb5918ce678811b6b1238c654f2e -
Branch / Tag:
refs/tags/v1.0.4 - Owner: https://github.com/MountainViewProvisions
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@1674ae528ed6cb5918ce678811b6b1238c654f2e -
Trigger Event:
push
-
Statement type: