Skip to main content

Generating Secrets

The Ghost Protocol requires three random secrets for each commitment. These must be cryptographically secure and stored safely.

Required Secrets

SecretPurpose
secretProves ownership of commitment
nullifierSecretUsed to derive nullifier (separate for privacy)
blindingHides dataHash in commitment

Generate Random Secrets

const FIELD_SIZE = 21888242871839275222246405745257275088548364400416034343698204186575808495617n;

function generateSecrets() {
function randomFieldElement() {
const bytes = crypto.getRandomValues(new Uint8Array(32));
const bn = BigInt('0x' + Buffer.from(bytes).toString('hex'));
return bn % FIELD_SIZE;
}

return {
secret: randomFieldElement(),
nullifierSecret: randomFieldElement(),
blinding: randomFieldElement(),
};
}

// Usage
const { secret, nullifierSecret, blinding } = generateSecrets();

Field Size Constraint

All values must be less than the BN254 field size:

21888242871839275222246405745257275088548364400416034343698204186575808495617

The modulo operation in randomFieldElement() ensures this constraint is satisfied.

Storing Secrets

Critical

If you lose these secrets before revealing, your commitment is permanently unrecoverable. There is no recovery mechanism.

Recommended storage:

  • Encrypted local storage
  • Secure database with encryption at rest
  • Hardware security module (HSM) for production

Token format for sharing:

const token = {
secret: '0x' + secret.toString(16).padStart(64, '0'),
nullifierSecret: '0x' + nullifierSecret.toString(16).padStart(64, '0'),
blinding: '0x' + blinding.toString(16).padStart(64, '0'),
dataHash: '0x' + dataHash.toString(16).padStart(64, '0'),
commitment: '0x' + commitment.toString(16).padStart(64, '0'),
leafIndex: leafIndex,
};

Browser vs Node.js

Browser:

const bytes = crypto.getRandomValues(new Uint8Array(32));

Node.js:

import { randomBytes } from 'crypto';
const bytes = randomBytes(32);

After Reveal

Once a commitment is revealed:

  • The nullifier is spent
  • The secrets are no longer needed
  • You can safely delete them
// After successful reveal
secrets.secret = null;
secrets.nullifierSecret = null;
secrets.blinding = null;