Generating Secrets
The Ghost Protocol requires three random secrets for each commitment. These must be cryptographically secure and stored safely.
Required Secrets
| Secret | Purpose |
|---|---|
secret | Proves ownership of commitment |
nullifierSecret | Used to derive nullifier (separate for privacy) |
blinding | Hides 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;