Skip to main content

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-ssl on 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-Origin CORS 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

archiviomd_verify-1.0.3.tar.gz (23.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

archiviomd_verify-1.0.3-py3-none-any.whl (20.3 kB view details)

Uploaded Python 3

File details

Details for the file archiviomd_verify-1.0.3.tar.gz.

File metadata

  • Download URL: archiviomd_verify-1.0.3.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

Hashes for archiviomd_verify-1.0.3.tar.gz
Algorithm Hash digest
SHA256 74060071963bd52fd4f68528565a4d5f57e548e21827c76d9f17b6c5ad0ca9ae
MD5 c9197bedc21e764d1dcefb828d9b1aeb
BLAKE2b-256 3f8142268f46ef59be5e2d6cd27303094fa3f6c53cd1fcb50411e668dc27ffb7

See more details on using hashes here.

Provenance

The following attestation bundles were made for archiviomd_verify-1.0.3.tar.gz:

Publisher: python-publish.yml on MountainViewProvisions/archiviomd-verify

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file archiviomd_verify-1.0.3-py3-none-any.whl.

File metadata

File hashes

Hashes for archiviomd_verify-1.0.3-py3-none-any.whl
Algorithm Hash digest
SHA256 b5d4dcdff08f7e72c71bcf063ac2bd230f054c1ce9c3fae73137ec2f64a80c1c
MD5 f069bf529f4c716b3f533a197d9046b2
BLAKE2b-256 5da202faa7eeab2e7c18bffa5f869522106a1c2744346067c032a19da4caaddb

See more details on using hashes here.

Provenance

The following attestation bundles were made for archiviomd_verify-1.0.3-py3-none-any.whl:

Publisher: python-publish.yml on MountainViewProvisions/archiviomd-verify

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page