Skip to main content

Phantom Keys

A phantom key is the sole proof of ownership for a Ghost Protocol commitment. It contains all the secret values needed to generate a ZK proof and reveal committed assets. There is no recovery mechanism, no admin override, and no account abstraction — if you lose the key, the committed assets are permanently inaccessible.

Core Principle

The key IS the proof of ownership.

A phantom key is not an access credential for a remote system. It is the cryptographic material itself. The secrets inside the key are the private inputs to the ZK circuit. Without them, it is computationally infeasible to generate a valid proof — even with unlimited access to the smart contracts and Merkle tree data.

There is no "forgot your password" flow. There is no multisig recovery. There is no admin key. This is a deliberate design choice: the same property that makes Ghost Protocol private (no on-chain link between commit and reveal) also makes phantom keys unrecoverable.

Key Formats

ghostchain-v2 (CommitRevealVault)

The standard format for token commitments through the CommitRevealVault:

{
"version": "ghostchain-v2",
"token": "0x0000000000000000000000000000000000000000",
"seed": "a1b2c3d4e5f67890a1b2c3d4e5f67890",
"secret": "1234567890abcdef...",
"nullifierSecret": "fedcba0987654321...",
"blinding": "1122334455667788...",
"amount": "1000000000000000000",
"commitment": "8765432109876543...",
"leafIndex": 42,
"tokenIdHash": "abcdef1234567890...",
"quantumSecret": "deadbeef01234567...",
"policyId": "0",
"policyParamsHash": "0",
"policyParams": ""
}

Field descriptions:

FieldTypeDescription
versionstringFormat identifier. Always "ghostchain-v2"
tokenstringToken contract address (zero address for native GHOST)
seedstring16-byte random seed used during key generation (hex)
secretstring31-byte random secret — primary circuit input (field element, decimal)
nullifierSecretstring31-byte random secret for nullifier derivation (field element, decimal)
blindingstringRandom blinding factor for commitment uniqueness (field element, decimal)
amountstringToken amount in base units (e.g., 10^18 for 1 GHOST)
commitmentstringPoseidon7 hash of all preimage values (field element, decimal)
leafIndexnumberPosition of the commitment in the Merkle tree
tokenIdHashstringPoseidon2(tokenAddress, 0) (field element, decimal)
quantumSecretstring32-byte quantum secret for post-quantum protection (hex). Empty string if unused
policyIdstringPolicy contract identifier (field element, decimal). "0" for no policy
policyParamsHashstringkeccak256(policyParams) % BN254_FIELD (field element, decimal). "0" for no policy
policyParamsstringABI-encoded policy parameters (hex). Empty string for no policy

open-ghost-persistent-v1 (PersistentKeyVault)

The format for persistent phantom keys, which can be accessed multiple times without spending:

{
"version": "open-ghost-persistent-v1",
"persistent": true,
"contentType": "application/json",
"encryptedSecret": "0xaabbccdd...",
"encKeyPartA": "0x11223344...",
"keyVaultId": "9876543210...",
"revokePolicy": "BEARER",
"secret": "1234567890abcdef...",
"nullifierSecret": "fedcba0987654321...",
"dataHash": "5566778899aabbcc...",
"blinding": "1122334455667788...",
"commitment": "8765432109876543...",
"leafIndex": 107,
"createdAt": "2026-01-15T08:30:00.000Z"
}

Field descriptions:

FieldTypeDescription
versionstringFormat identifier. Always "open-ghost-persistent-v1"
persistentbooleanAlways true — distinguishes from one-time keys
contentTypestringMIME type of the encrypted payload
encryptedSecretstringAES-encrypted payload (hex)
encKeyPartAstringFirst half of the AES key — stored in this file
keyVaultIdstringOn-chain identifier for the key's vault entry
revokePolicystring"BEARER" or "ISSUER_ONLY" — who can revoke
secretstringZK circuit secret (field element, decimal)
nullifierSecretstringNullifier derivation secret (field element, decimal)
dataHashstringHash of the encrypted data (field element, decimal)
blindingstringBlinding factor (field element, decimal)
commitmentstringPoseidon4 hash of the preimage (field element, decimal)
leafIndexnumberPosition in the Merkle tree
createdAtstringISO 8601 timestamp of key creation

Export Formats

Phantom keys must be durably stored outside the browser. Ghost Protocol supports multiple export formats, each optimized for different use cases.

PNG Image

The primary export format. The phantom key JSON is embedded in the PNG file's metadata using steganographic encoding:

┌──────────────────────────────────┐
│ │
│ Visual card design │
│ (amount, token, timestamp) │
│ │
│ ┌────────────────────────────┐ │
│ │ Embedded metadata: │ │
│ │ - Full phantom key JSON │ │
│ │ - Key version │ │
│ │ - Integrity checksum │ │
│ └────────────────────────────┘ │
│ │
└──────────────────────────────────┘

Properties:

  • File appears as a normal image — does not look like a cryptographic key
  • Can be saved to camera roll, AirDrop, cloud storage
  • Integrity checksum verifies the key has not been corrupted
  • The import flow reads the embedded metadata from the PNG to reconstruct the key

PDF Voucher

A printable document containing the phantom key as both human-readable data and machine-readable QR codes:

  • Full phantom key JSON encoded as a QR code
  • Human-readable fields: amount, token, commitment (truncated), creation date
  • Instructions for redemption
  • Suitable for physical distribution (gift cards, paper wallets)

QR Code

A standalone QR code encoding the phantom key JSON:

  • Used for screen-to-screen transfers
  • Displayed temporarily in the app for scanning
  • Not recommended for long-term storage (no visual context, easy to confuse with other QR codes)

NFC (NTAG 424 DNA)

Phantom keys can be written to NFC hardware cards using the NTAG 424 DNA chip:

┌─────────────────────────────┐
│ NTAG 424 DNA Card │
│ │
│ NDEF Record: │
│ ├── Type: application/json│
│ ├── Payload: phantom key │
│ └── SUN authentication │
│ │
│ Hardware features: │
│ ├── Tamper detection │
│ ├── AES-128 encryption │
│ ├── Rolling SUN counter │
│ └── One-tap NFC read │
│ │
└─────────────────────────────┘

NTAG 424 DNA features:

FeatureDescription
SUN (Secure Unique NFC)Each tap generates a unique authentication code, preventing relay attacks
AES-128On-chip encryption protects the stored key data
Tap counterMonotonic counter increments on each read — detects cloning attempts
Tamper detectPhysical tamper loop can detect if the card has been opened

NFC cards turn phantom keys into physical bearer instruments — the person holding the card can reveal the committed assets by tapping their phone.

Numeric Code

A human-typeable representation of the phantom key, designed for phone dictation or manual entry:

Format:  XXXX-XXXX-XXXX-XXXX-XXXX-XXXX-XXXX-XXXX
└──────────── V4 with quantum secret ────────────┘

The V4 numeric format includes the quantum secret, ensuring that manually entered keys retain full quantum protection. The code uses a restricted character set (digits only) with checksum segments for error detection.

Security Properties

No Recovery

ScenarioOutcome
Lost phantom key (all copies)Assets permanently locked — no one can generate the ZK proof
Corrupted phantom keyAssets permanently locked — incorrect secrets produce invalid proofs
Stolen phantom keyThief can reveal the assets — the key is the only authentication
Copied phantom keyFirst to reveal wins — nullifier prevents second reveal
Forgotten passwordN/A — phantom keys are not password-protected by default

Bearer Property

Phantom keys are bearer instruments. Whoever possesses the key can reveal the assets. This is analogous to physical cash:

  • Possession = ownership. There is no identity verification, no KYC check, no wallet signature required at reveal time. The ZK proof itself is the authentication.
  • Transferability. Sending someone a phantom key (via AirDrop, email, NFC tap) transfers the ability to reveal. This is how Ghost Protocol enables cash-like digital assets.
  • Risk. If a key is intercepted, the interceptor can reveal before the intended recipient. For high-value transfers, policies (e.g., DestinationRestriction) can mitigate this risk.

Commitment Binding

The phantom key is cryptographically bound to its commitment. Every field in the key is either a direct input to the Poseidon hash or derived from one:

commitment = Poseidon7(
key.secret,
key.nullifierSecret,
key.tokenIdHash, ← derived from key.token
key.amount,
key.blinding,
key.policyId,
key.policyParamsHash
)

If any field is modified, the resulting commitment will not match the on-chain commitment, and the Merkle proof will fail. Phantom keys cannot be forged or tampered with.

Key Lifecycle

  ┌──────────┐    ┌──────────┐    ┌──────────┐    ┌──────────┐
│ Generate │───►│ Export │───►│ Store │───►│ Import │
│ │ │ │ │ │ │ │
│ secrets │ │ PNG/PDF/ │ │ camera │ │ scan/ │
│ compute │ │ QR/NFC/ │ │ roll, │ │ upload/ │
│ commit │ │ numeric │ │ cloud, │ │ tap NFC │
└──────────┘ └──────────┘ │ NFC card │ └────┬─────┘
└──────────┘ │

┌──────────┐
│ Reveal │
│ │
│ generate │
│ ZK proof │
│ submit │
└──────────┘
  1. Generate: Random secrets are generated client-side. The commitment is computed. The phantom key JSON is assembled.
  2. Export: The key is rendered into one or more export formats (PNG, PDF, QR, NFC, numeric).
  3. Store: The user saves the exported key. This is the critical step — the key must survive browser closure.
  4. Import: When ready to reveal, the user imports the key by scanning, uploading, or tapping.
  5. Reveal: The imported key provides all the private inputs needed to generate the ZK proof and submit the reveal transaction.