Nukez

§ proof · verification guide

Don't trust Nukez. Verify it.

Every Nukez receipt is independently checkable in four ways. No account, no API key, and no trust in Nukez required — the verification path is public by design.

4 levels · independentSHA-256 · Ed25519 · secp256k1No account required

§ level 1 · file integrity

Did the bytes change?

After downloading a file from a Nukez locker, compute its SHA-256 hash locally and compare against the content_hash recorded in the locker manifest.

import hashlib

# Download the file bytes (via SDK, MCP, or raw HTTP)
file_bytes = downloaded_content

# Compute SHA-256
local_hash = "sha256:" + hashlib.sha256(file_bytes).hexdigest()

# Compare against manifest entry
assert local_hash == manifest_entry["content_hash"]

Match — the file you hold is byte-identical to what was stored. Mismatch — the content has been modified since storage.

§ level 2 · manifest + merkle integrity

Did the set of files change?

The manifest lists every file with filename, size, and content hash. The merkle root is computed deterministically from these entries — any change to any file produces a different root.

Merkle leaf

leaf = SHA256("{filename}:{size_bytes}:{content_hash}")

content_hash is the raw hex digest in the leaf computation (no sha256: prefix).

Merkle tree (bottom-up)

  • Sort all leaves alphabetically by filename.
  • Compute SHA-256 of each leaf string.
  • Pair leaves left-to-right; if odd, the last leaf pairs with itself.
  • Parent = SHA-256(left_hex + right_hex) — concatenate the hex strings, then hash.
  • Repeat until one root remains.
import hashlib

def build_merkle_root(file_entries):
    """
    file_entries: list of dicts with 'filename', 'size_bytes', 'content_hash'
    content_hash values should be raw hex (no 'sha256:' prefix)
    """
    if not file_entries:
        return hashlib.sha256(b"empty").hexdigest()

    sorted_entries = sorted(file_entries, key=lambda e: e["filename"])

    # Compute leaf hashes
    leaves = []
    for entry in sorted_entries:
        raw_hash = entry["content_hash"].replace("sha256:", "")
        leaf_data = f"{entry['filename']}:{entry['size_bytes']}:{raw_hash}"
        leaf_hash = hashlib.sha256(leaf_data.encode("utf-8")).hexdigest()
        leaves.append(leaf_hash)

    # Build tree bottom-up
    level = leaves
    while len(level) > 1:
        next_level = []
        for i in range(0, len(level), 2):
            left = level[i]
            right = level[i + 1] if i + 1 < len(level) else level[i]
            combined = hashlib.sha256((left + right).encode("utf-8")).hexdigest()
            next_level.append(combined)
        level = next_level

    return level[0]

Compare your computed root against the merkle_root in the attestation. Match means no file has been added, removed, modified, or reordered since attestation.

Skip the loop: recompute-verify

Rather than rebuilding the tree yourself, you can ask the gateway to do it. This is a convenience, not a trust dependency — you can always recompute locally. The endpoint is public, no authentication required.

GET /v1/storage/recompute-verify?receipt_id={receipt_id}

# Response
{
    "match": true,
    "receipt_id": "8239fc15efc46042",
    "locker_id": "locker_62e358731c6f",
    "computed": "sha256:6a0c80f5c0a3...",
    "stored":   "sha256:6a0c80f5c0a3...",
    "file_count": 1,
    "recompute_ms": 1040
}

If match is false, either the locker contents changed since attestation, or the stored attestation was tampered with. Either way — you know.

§ level 3 · receipt signature

Did the gateway sign it?

The receipt includes an Ed25519 signature over the merkle root. Verify it with the signer's public key — both ship in the receipt.

from nacl.signing import VerifyKey
import binascii

receipt = get_receipt(receipt_id)  # the full receipt object
pubkey = receipt["receipt_signer_pubkey"]
sig    = receipt["receipt_sig"]

# The signed payload is the merkle_root hex string, UTF-8 encoded.
signed_payload = receipt["merkle_root"].encode("utf-8")

vk = VerifyKey(binascii.unhexlify(pubkey))
vk.verify(signed_payload, binascii.unhexlify(sig))  # raises if forged

Combined with Level 2 — which binds the manifest to the merkle root — this transitively binds the manifest to the signer. Any modification to the manifest produces a different root, and the signature no longer covers it.

§ level 4 · on-chain attestation

Did Solana see the same root?

Nukez anchors attestations on Solana through two complementary mechanisms. Either is sufficient on its own; together they give you both a numerical comparison and a permanent log entry.

Switchboard oracle feed

The attestation code (att_code) is pushed to a Switchboard PullFeed account on Solana. The code is derived from the merkle root — so anyone with the root can recompute it and compare.

def att_code_from_hash(h):
    """First 12 hex chars (48 bits) as int, clamped to 9 digits."""
    return int(h[:12], 16) % 1_000_000_000

The oracle's Ed25519 signature over the quote is verified by Solana's Ed25519 precompile — no trust in the oracle itself is needed.

SPL Memo

The full attestation metadata is written as an SPL Memo in the same transaction — permanently readable in the Solana transaction log via any block explorer.

{
    "schema": "nukez/attestation/v1",
    "receipt_id": "8239fc15efc46042",
    "merkle_root": "sha256:abc123...",
    "file_count": 42,
    "attested_at": "2026-02-11T..."
}

Verifying on-chain

  1. Get the tx_signature from the attestation response (or from the receipt's switchboard.tx field).
  2. Look it up: https://explorer.solana.com/tx/{tx_signature}.
  3. Find the “Program Log: Memo” entry.
  4. Confirm the memo contains the expected receipt_id and merkle_root.

§ tamper evidence

Every attack vector. Detected.

Every modification produces a different merkle root. There is no way to modify content and preserve the root — the math does not allow it.

AttackWhat changesDetection
Modify a file's contentContent hash changes → leaf changes → root changesRoot mismatch vs. on-chain attestation
Delete a fileLeaf count drops → tree structure changesRoot mismatch
Add a fileLeaf count increases → new rootRoot mismatch
Swap a file (same name, different content)Content hash changes → leaf changesRoot mismatch
Reorder filesLeaves are sorted by filename — order is canonicalNot possible by construction
Forge the manifestMerkle root changes; receipt signature covers the rootRoot mismatch or signature verification fails

§ extending the chain

Verification further down.

§ cross-agent

No shared keys. No shared accounts.

Agent A stores data and gets a receipt_id. Agent A passes it to Agent B. Agent B verifies — locally or via recompute-verify — using only the receipt ID. Agent B now has independent cryptographic proof of what Agent A stored, when, and that it hasn't been tampered with.

§ gateway self-verify

Verifying the verifier.

The gateway hashes its own running source against an on-chain attestation. If the gateway's code has been modified after deployment, the verification fails.

GET /v1/self-verify

Supported signatures

Both algorithms produce the same receipt structure, the same verification path, and the same attestation chain. Neither is primary — both are first-class.

AlgorithmChainKey formatUse case
Ed25519SolanaBase58 public keySolana-native wallets and agents
secp256k1EVM / MonadEthereum address (0x…)EVM wallets, Monad chain payments

§ cheat sheet

Five questions. Five answers.

QuestionHow to checkWhat it proves
Is my downloaded file authentic?SHA-256 locally; compare to manifest content_hashFile is byte-identical to the stored version
Is the manifest intact?Rebuild merkle tree from file entries; compare to merkle_rootNo files added, removed, or modified since attestation
Was the receipt forged?Ed25519 signature verification with gateway public keyReceipt was produced by the gateway, unaltered
Is the attestation on-chain?Look up tx_signature on Solana Explorer; read SPL MemoMerkle root was committed to Solana at a specific slot
Can I verify without trusting Nukez?Yes — every step uses public data and standard cryptographyThe entire point

§ next

Verify a real receipt.

Paste a receipt ID into the attestation explorer to run all four checks in one place — or jump to the integration docs to wire verification into your stack.