Skip to content

Verify a file

For anyone outside Permafrost — a counterparty, an auditor, a user sent a file. They need the file, and for a salted fingerprint, the default for a file stored encrypted, its salt from you.

No Authorization header.

40-verify.sh
# Verification takes no key: no Authorization header on either call below.
# Anyone holding the bytes can ask whether Permafrost holds provenance.
#
# Verify indexes the STORED hash - the bytes as stored - so the first call
# answers provenance true. Asking with CERT_FINGERPRINT legitimately answers
# provenance false: that is what the certificate names, not what storage
# indexes.
curl -sS -m 60 "$HOST/v1/api/verify?hash=$STORED_HASH"
echo
curl -sS -m 60 "$HOST/v1/api/verify?hash=$CERT_FINGERPRINT"
echo

Pass the hash as 64 hex characters (shasum -a 256 <file> for a plaintext fingerprint). A salted fingerprint isn’t found by the file’s own hash: check it with the verifier, the file and its salt. When provenance is held:

{
"hash": "…",
"provenance": true,
"nft_id": "0x…",
"content_hash": "…",
"certified": true,
"explorer_url": "https://…/object/0x…"
}

nft_id is the receipt’s id on Sui (the receipt is an object there). certified is true once on Walrus.

What the verdict says, and what it doesn’t

Section titled “What the verdict says, and what it doesn’t”
  • true: these exact bytes were stored and recorded witnessed.
  • false: no record, or the wrong hash — an encrypted custody object is recorded by its stored hash.
  • Not said: who stored it, or whether it’s still retrievable (Retention).

Follow explorer_url or paste nft_id into any Sui explorer; no account or wallet needed. The receipt carries:

  • the fingerprint and its kind, so anyone with the file knows what to compute;
  • size and file count;
  • whether the stored bytes were encrypted;
  • the previous receipt, for a new version;
  • the locator of what it covers on Walrus (Leaving).

Receipts can’t be transferred or changed: they stay with what they attest, as written. verifiable

Network Manifest package Incineration package
testnet 0xe920e99e6a264b8b00c3d7e2824b9c3db624bccedc26e25b5095fd41ba8cc484 0x7beda97acf07c60d9839a64166b59d10e3cdc3b42fa955fcc8dd23049910ac44

pf-verify, provided at onboarding, checks a receipt from Sui alone, with no call to the deployment verifiable:

pf-verify receipt <receipt id> --rpc <a Sui gRPC url> [--file <path>] [--salt <hex>]

Without --file it checks the receipt on its own. Add --file <path> to match a file you hold, and --salt <hex> for a salted fingerprint. Exit 0 is valid, 1 invalid, 3 the chain or the public copy couldn’t be read.

A deleted file leaves a certificate instead of a receipt. Check it with the published verifier:

pf-verify custody <certificate id> --deployment <the deployment's URL> --rpc <a Sui gRPC url>

Name the operator yourself with --attester <address> instead of --deployment; one of the two is required. Add --file <path> --salt <hex> to match a file you hold to the certificate. Exit 0 is valid, 1 invalid, 3 the chain couldn’t be read.

The certificate shows that the named operator attested the key’s destruction at that epoch (a Sui epoch, not a time) and names the content verifiable. The destruction itself is the operator’s word our statement. It doesn’t show that every copy is gone: Walrus keeps the ciphertext until its epochs end. Custody and deletion

Permafrost runs on Sui testnet and Walrus testnet. Everything here describes a shipped testnet instance, not a production service.