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.4.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.4-py3-none-any.whl (20.3 kB view details)

Uploaded Python 3

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

Hashes for archiviomd_verify-1.0.4.tar.gz
Algorithm Hash digest
SHA256 b1566f55d98f84538e04e2b5327f1628cdf4c05b0ab953b11349a4eedea65dbb
MD5 e3762eb02daaffa9d1ae3e6faf858c4c
BLAKE2b-256 d0e0c39d4b360a509e643d606be5efb9a8c53b85ddab36c58495505f2198f048

See more details on using hashes here.

Provenance

The following attestation bundles were made for archiviomd_verify-1.0.4.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.4-py3-none-any.whl.

File metadata

File hashes

Hashes for archiviomd_verify-1.0.4-py3-none-any.whl
Algorithm Hash digest
SHA256 dd30c34a08cda3c71f92efa12c66731cbb1af4ec2ad44dea17389e46c1870c88
MD5 c4bdabe7ef714576a400ff524bdfa5e2
BLAKE2b-256 268ac2b4faaa721eea385ac98cdbbad963dd3d10b14a471292692f6c6ef208bd

See more details on using hashes here.

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

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