> ## Documentation Index
> Fetch the complete documentation index at: https://docs.presschain.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Content Hashing

> Use deterministic content and metadata commitments so independent applications can verify the same artifacts.

# Content hashing

Hashes are what allow an external artifact to remain verifiable even when the bytes themselves live outside contract storage. They are only useful when every implementation agrees on exactly which bytes were hashed.

## Define a canonical representation

If a newsroom hashes rendered HTML that contains timestamps, rotating ad markup or random IDs, the hash can change between requests even though the story appears identical.

Choose a stable representation. Examples include normalized HTML, Markdown, a signed JSON document or an archival export.

Document the choice in your integration.

## Metadata is canonicalized separately

Capsule metadata V1 has a canonical Rust implementation. It normalizes whitespace for required fields, enforces the schema version, lowercases content type and language, validates optional cover hash format and serializes canonical JSON bytes before hashing.

Use that implementation or a test-vector-compatible port.

## Never hash a URL as a substitute for content

This is wrong:

```ts theme={null}
const hash = keccak256(toUtf8Bytes("https://example.org/story"));
```

It commits to the URL string, not the bytes served by the URL.

Instead, fetch or export the canonical artifact and hash those bytes.

## Preserve algorithm context

A 32-byte value does not tell a future reader which hash algorithm produced it. Where the protocol fixes an algorithm, follow it exactly. Where an application adds extra hashes, record the algorithm in metadata.

```json theme={null}
{
  "algorithm": "sha256",
  "value": "0x..."
}
```

## Verification function

A verifier should fail closed on mismatched bytes.

```ts theme={null}
async function verifyArtifact(url: string, expected: string) {
  const res = await fetch(url);
  if (!res.ok) return { state: "unavailable" as const };

  const bytes = await res.arrayBuffer();
  const digest = await crypto.subtle.digest("SHA-256", bytes);
  const actual = "0x" + Array.from(new Uint8Array(digest), b => b.toString(16).padStart(2, "0")).join("");

  return actual.toLowerCase() === expected.toLowerCase()
    ? { state: "verified" as const, actual }
    : { state: "mismatch" as const, actual };
}
```

Use the protocol-required algorithm for the field you are verifying. The example demonstrates the control flow.

## Hashes prove integrity, not truth

A matching hash proves that the bytes you retrieved match the committed bytes. It does not prove that the statements inside those bytes are accurate.

That is why PressChain also models identity, evidence, reviews, challenges and provenance.
