EPX/1 — Image Provenance Format

Version 1.0 · SHA-256 · Ed25519 · Canonical JSON · Append-only event chain

1. Overview

EPX/1 is an open format for recording the provenance of digital image files. A manifest is a JSON document that accompanies an image, recording its origin, cryptographic hash, edit history, and a digital signature from the signing entity.

Manifests are stored as sidecar files alongside the image. The preferred filename is <image_filename>.epx.json.

While EPX/1 is an open format that any implementor may adopt, the VeriChain Directory — which confirms signer identity — is a curated ecosystem. Registration is available only through VeriChain-authorised applications, ensuring the integrity of the identity layer.

2. Required top-level fields

FieldTypeDescription
format_idstringMust be "EPX/1"
manifest_versionstringMust be "1.0"
object_uuidstringLowercase UUID v4. Stable for the lifetime of the image.
parent_manifest_hashstring | nullSHA-256 hex of the previous manifest. null for genesis.
content_hash_algstringMust be "sha-256"
content_hashstringLowercase hex SHA-256 of the raw image file bytes.
metadata_hash_algstringMust be "sha-256"
signature_algstringMust be "ed25519"
canonicalization_profilestringMust be "epx1-canonical-json-v1"
signer_key_idstringIdentifies the signing key and the ecosystem app that created it. Format: {app_id}:{uuid} — e.g. verilens:550e8400-…. The app_id is a short lowercase identifier for the VeriChain ecosystem app (e.g. verilens). The UUID is the user's permanent VeriChain identity.
captureobjectCapture metadata. Must include timestamp.
eventsarrayOrdered list of edit events. Empty for genesis manifests.
manifest_hashstringLowercase hex SHA-256 of the canonical manifest (excluding signature and manifest_hash).
signaturestringLowercase hex Ed25519 signature over the manifest_hash bytes (UTF-8).

3. Canonicalization — epx1-canonical-json-v1

The manifest hash is computed from a canonical serialisation of the manifest object. The following rules apply:

4. Signing procedure

  1. Remove signature and manifest_hash fields from the manifest object
  2. Serialise the remaining object using canonical JSON (§3)
  3. Compute SHA-256 of the canonical bytes → this is the manifest_hash
  4. Sign the UTF-8 bytes of the hex-encoded manifest_hash string using Ed25519 → this is the signature
  5. Set both fields on the manifest object

5. Event types

TypeDescription
cropSpatial crop. Params: x, y, w, h (normalised 0–1)
rotateRotation. Params: degrees
brightnessTonal adjustment. Params: brightness, contrast, saturation (–100 to +100)
contrastContrast adjustment. Params: contrast
resizeResize. Params: width_pct, height_pct
denoiseNoise reduction. Params: amount (0–100)
color_adjustColour grading. Params: saturation, warmth
ai_generateAI-generated content introduced. Must be declared explicitly.
otherArbitrary edit. Params: note (string)

Event object structure

FieldRequiredDescription
typeYesOne of the event types above
timestampYesRFC 3339 UTC timestamp, e.g. 2026-04-11T09:41:00Z
paramsNoKey/value pairs specific to the event type
toolNoIdentifier of the tool that performed the edit

6. Verification rules

A conforming verifier must perform all of the following checks in order:

  1. Format checkformat_id must equal "EPX/1" and manifest_version must equal "1.0"
  2. Required fields — all fields listed in §2 must be present
  3. Content hash — recompute SHA-256 of image bytes and compare to content_hash
  4. Manifest hash — recompute canonical hash per §3 and compare to manifest_hash
  5. Signature — verify Ed25519 signature over manifest_hash bytes using the signer's public key
  6. Hash-chain continuity (if parent available) — parent_manifest_hash must equal the manifest_hash of the previous revision

7. Storage model

EPX/1 supports three storage models in order of preference:

  1. Sidecar file<filename>.epx.json alongside the image (recommended)
  2. Embedded EXIF/private IFD — for JPEG/TIFF files where sidecar management is difficult
  3. XMP mirror — for interoperability with existing DAM systems

8. Unknown fields

Unknown non-critical fields must be preserved when reading and rewriting a manifest. Implementations must not drop fields they do not recognise. Use a vendor prefix (e.g. x_acme_gps) for custom fields to avoid future collisions with reserved EPX/1 names.

9. Example manifest

{
  "canonicalization_profile": "epx1-canonical-json-v1",
  "capture": {
    "device": "iPhone 17 Pro",
    "software": "VeriLens/1.0",
    "timestamp": "2026-04-11T09:41:00Z"
  },
  "content_hash": "cf56017fda1e2c63ba6003984985bbd7b2e023ae6dc6122388f819c8654cd776",
  "content_hash_alg": "sha-256",
  "events": [],
  "format_id": "EPX/1",
  "manifest_hash": "57cd22156c2ad5a7f50615dbe0cc899eb431703cc19c264b5f9ae95a57987091",
  "manifest_version": "1.0",
  "metadata_hash_alg": "sha-256",
  "object_uuid": "96541304-b68e-4de7-91f1-96ff731a5c9d",
  "parent_manifest_hash": null,
  "signature": "aabb...ccdd",
  "signature_alg": "ed25519",
  "signer_key_id": "verilens:550e8400-e29b-41d4-a716-446655440000"
}

10. Out of scope for v1.0

The Technology Behind VeriChain See VeriLens