Skip to content

Verify an attestation

Every endpoint carries a signed statement of exactly what it serves: the Civitai model and version it came from, the SHA-256 published there, the SHA-256 we measured on the bytes we fetched, the compiled artifact hash, and the verified owner identity. For composed endpoints the statement includes the ordered component list with scales — the full stack, as served.

The point: you don't have to trust our API. Fetch the signing key once, then verify any statement offline, forever.

The key

curl -s https://epm-router.uridemay.workers.dev/.well-known/epm-attestation
{
  "algorithm": "ed25519",
  "public_key": "…hex…",
  "canonicalization": "JSON, sorted keys, compact separators, UTF-8"
}

Verify offline

import json
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey

def verify(public_key_hex: str, statement: dict, signature_hex: str) -> bool:
    key = Ed25519PublicKey.from_public_bytes(bytes.fromhex(public_key_hex))
    canonical = json.dumps(
        statement, sort_keys=True, separators=(",", ":")
    ).encode()
    try:
        key.verify(bytes.fromhex(signature_hex), canonical)
        return True
    except Exception:
        return False

att = ...  # the response of GET /v1/models/{id}/attestation
assert verify(att["public_key"], att["statement"], att["signature"])

What the statement proves

  • source.published_sha256 vs source.measured_sha256: the file Civitai advertises is the file we actually fetched and compiled. Compare published_sha256 against the Civitai listing yourself for end-to-end, no-trust verification.
  • verified_source_identity / verification_method: the account that onboarded this model proved control of the Civitai listing.
  • artifact.core_hash: the content address of the compiled weights being served — the same hash the serving pod loads by.
  • For endpoints: components[] in canonical fuse order with scale — additive fusion is order-dependent at the bit level, so the order is part of the identity being attested.