Verification Specification
Independent verification requires no SDK, no account, and no trust in CertifiedData beyond the published public key. This document specifies the exact verification procedure.
Two levels of verification
Level 1 — Signature verification
Confirms the certificate was genuinely issued by CertifiedData.io and has not been tampered with. Available for all certificates (cert.v1 and cert.v2).
Level 2 — File hash verification
Confirms your downloaded file matches the specific bytes recorded at certification time. Requires a cert.v2 certificate with dataset_hash.
Step 1: Verify the file hash
Compute the SHA-256 hash of your downloaded file and compare it against dataset_hash (for the ZIP) or inner_artifacts["dataset.csv"].sha256 (for the extracted CSV) in the certificate.
# Verify ZIP archive hash sha256sum your-dataset.zip # Expected: matches dataset_hash in the certificate (without "sha256:" prefix) # Verify extracted CSV hash sha256sum dataset.csv # Expected: matches inner_artifacts["dataset.csv"].sha256
A mismatch means the file bytes differ from what was certified. Either the file was modified, corrupted in transit, or the wrong file is being verified.
Step 2: Verify the Ed25519 signature
Fetch the active public key from /.well-known/signing-keys.json and verify the certificate signature using any standard Ed25519 library.
# 1. Fetch the certificate
curl https://certifieddata.io/api/certificates/{certId} > cert.json
# 2. Fetch the public key
curl https://certifieddata.io/.well-known/signing-keys.json > keys.json
# 3. Verify using openssl (Ed25519)
# Extract signature and payload, then:
openssl pkeyutl -verify -pubin -inkey pubkey.pem -sigfile sig.bin -in payload.binThe signature is computed over the RFC 8785 canonical JSON serialization of all certificate fields except the signature field itself. This is the same payload returned by GET /api/certificates/{certId}/download.
API verification endpoint
CertifiedData provides a public verification endpoint that performs both checks server-side. No authentication required.
POST /api/verify
# Request body
{
"certificate_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"artifact_hash": "sha256:a3f8b2c1..." // optional — provide for file hash check
}
# Success response (200)
{
"verified": true,
"certificate_id": "3fa85f64-...",
"issuer": "CertifiedData.io",
"algorithm": "ctgan",
"timestamp": "2026-03-16T00:00:00Z",
"hash_match": true, // present when artifact_hash was provided
"signature_valid": true
}
# Failure response (200, verified: false)
{
"verified": false,
"reason": "hash_mismatch" // or: "certificate_not_found", "signature_invalid"
}Browser verification
Upload any file at /verify or navigate to certifieddata.io/verify/{certId} directly. The verification page computes the SHA-256 hash client-side (in-browser) and compares it against the certificate — the file bytes never leave your machine.
Trust model
The verification procedure requires trust in exactly one thing: the public key at /.well-known/signing-keys.json. If you independently confirm this is the genuine CertifiedData public key (via DNS, PKI, or out-of-band confirmation), then:
- A valid signature proves the certificate was issued by CertifiedData
- A matching hash proves your file is byte-for-byte identical to what was certified
- Both together prove the artifact was synthetically generated at the stated time by the stated algorithm