brainvault
v1.0.1
Published
Memory-hard deterministic key derivation from human-memorable credentials
Maintainers
Readme
BrainVault
Memory-hard deterministic key derivation from human-memorable credentials.
CRITICAL: AIR-GAP MANDATORY
This tool generates cryptocurrency keys. Run ONLY on air-gapped machines. NEVER run on internet-connected devices. Compromised keys mean PERMANENT FUND LOSS.
NOT AUDITED - BETA SOFTWARE
This software and its dependencies (including @noble/post-quantum) have NOT been professionally audited. Use ONLY small test amounts until community review and professional audit.
BEFORE FUNDING: TEST CREDENTIAL RECALL
Forgotten credentials mean permanent fund loss. Before sending any funds:
- Generate keys and save receipt
- Verify you can reproduce the fingerprint 5-10 times over several days
- Start with small test amounts ($10-100)
- Only increase amounts after successful recall testing
What It Does
BrainVault derives deterministic cryptographic keys from:
- An identity (email/username)
- A master password
- Configurable security parameters
It outputs:
- SLH-DSA-SHAKE-256s keypair (NIST FIPS 205, post-quantum secure)
- 24-word BIP39 mnemonic (optional, for existing cryptocurrency wallets)
- High-entropy Base58 password (optional, for legacy applications)
Why Memory-Hard?
Traditional brain wallets are vulnerable to brute-force attacks. BrainVault uses Argon2id with aggressive memory requirements (64MB-1GB per hash) and parallel lane saturation. This forces attackers to use substantial RAM per guess, making large-scale attacks economically impractical.
Installation
# Global installation (for CLI)
npm install -g brainvault
# Or run directly with npx
npx brainvault
# As a library
npm install brainvaultCLI Usage
Generate Keys
# Interactive mode
npx brainvault
# With receipt (re-hydrates previous settings)
npx brainvault --receipt ./my-receipt.jsonVerify Credentials
# Verify you can reproduce the same fingerprint
npx brainvault-verify ./my-receipt.json
# Manual parameter entry
npx brainvault-verify --manualLibrary Usage
import { deriveKeys, createConfig, Profile, OutputMode } from 'brainvault';
const config = createConfig({
identity: '[email protected]',
password: Buffer.from('my-secure-password'),
profile: Profile.Standard,
generation: 0,
factor: 3,
outputMode: OutputMode.PQ,
});
const result = await deriveKeys(config, {
onProgress: (current, total) => {
console.log(`Progress: ${current}/${total}`);
},
});
// Post-quantum keys (primary output)
console.log(result.pq.publicKey.pem); // PEM-formatted public key
console.log(result.pq.secretKey.pem); // PEM-formatted secret key
console.log(result.pq.keypair); // Raw Uint8Array keypair
// Legacy outputs (when outputMode is OutputMode.Legacy or OutputMode.Both)
console.log(result.legacy?.mnemonic); // 24-word BIP39 phrase
console.log(result.legacy?.appPassword); // Base58 password (xxxx-xxxx-xxxx-xxxx)
console.log(result.fingerprint); // 12-char verification fingerprint
// IMPORTANT: Zero sensitive buffers when done
result.zero();Browser Usage
BrainVault works in browsers via Web Workers for non-blocking derivation:
import { createWorker, deriveInWorker } from 'brainvault/worker';
const worker = createWorker();
const result = await deriveInWorker(worker, config, (current, total) => {
console.log(`Progress: ${current}/${total}`);
});Security Profiles
| Profile | Memory | Threads | Use Case | |---------|--------|---------|----------| | Portable | 64 MB | 1 | Travel/low-spec devices | | Standard | 256 MB | 4 | Desktop computers | | Bunker | 1 GB | 8 | Cold storage, maximum security |
Time Factor Guide
| Factor | Base Shards | Approx. Time (Standard) | |--------|-------------|-------------------------| | 1 | 16 | ~5 seconds | | 3 | 64 | ~20 seconds | | 5 | 256 | ~2 minutes | | 7 | 1024 | ~8 minutes | | 9 | 4096 | ~30 minutes |
Weak passwords incur additional penalty shards (up to 2048 extra).
Password Strength
BrainVault analyzes password strength and applies penalties:
| Entropy (log10) | Penalty | Assessment | |-----------------|---------|------------| | < 12 | BLOCKED | Too weak, cannot proceed | | 12-14 | +2048 shards | Weak | | 14-18 | +512 shards | Moderate | | 18+ | None | Strong |
Receipt Files
After generation, a receipt JSON is saved containing:
- Partial identity hash (for verification)
- Profile, generation, factor settings
- Fingerprint (for credential recall testing)
- NO secrets
Use receipts to:
- Re-hydrate settings on future runs
- Verify you remember credentials correctly
- Document your setup (store separately from passwords)
Algorithm
1. identityHash = SHA3-256(identity)
2. For each shard i in [0, totalShards):
salt = SHA3-256(identityHash | shardIndex | generation | ALG_TAG)
shard[i] = Argon2id(password, salt, memCost, timeCost=2, parallelism)
3. masterIKM = SHA3-512(header | shard[0] | ... | shard[n])
4. slhDsaSeed = HKDF-SHA512(masterIKM, "BrainVault-v3-SLH-DSA-SHAKE-256s-Seed", 96)
5. (secretKey, publicKey) = SLH-DSA-SHAKE-256s-KeyGen(slhDsaSeed)
6. [Optional] mnemonicEntropy = HKDF-SHA512(masterIKM, "BrainVault-v3-BIP39-Mnemonic", 32)
7. [Optional] passwordEntropy = HKDF-SHA512(masterIKM, "BrainVault-v3-Base58-Password", 64)Full specification: See ALGORITHM.md
Critical Limitations
This is beta software. Do NOT use for amounts you cannot afford to lose.
Unaudited Dependencies
BrainVault uses @noble/post-quantum for SLH-DSA signatures. This library:
- Has NOT been professionally audited
- Is version 0.x (pre-stable API)
- Is the foundation of all post-quantum security claims
If @noble/post-quantum has bugs, your keys are compromised regardless of password strength.
JavaScript Memory Model
JavaScript cannot guarantee secure memory handling:
zeroBytes()overwrites buffers but V8 may retain copies in memory- Garbage collection timing is unpredictable
- String passwords are interned and cannot be zeroed
Mitigation: Reboot the machine after key generation. Use air-gapped dedicated hardware.
What Could Go Wrong
| Risk | Impact | Mitigation | |------|--------|------------| | Password forgotten | Total fund loss | Test recall extensively before funding | | @noble/post-quantum bug | Key compromise | Wait for audit, use small amounts | | Air-gap violated | Key theft | Dedicated offline machine | | JavaScript memory leak | Key exposure | Reboot after generation |
API Reference
createConfig(params)
Create a derivation configuration with validation and Unicode normalization.
interface ConfigParams {
identity: string; // Email or username
password: Buffer; // Master password
profile?: Profile; // Default: Profile.Standard
generation?: number; // Default: 0 (increment to rotate keys)
factor?: number; // Default: 3 (1-9, controls work factor)
outputMode?: OutputMode; // Default: OutputMode.PQ
}deriveKeys(config, options?)
Main derivation function. Returns post-quantum and/or legacy keys.
interface DerivationResult {
fingerprint: string;
algo: string;
totalShards: number;
penaltyShards: number;
baseShards: number;
outputMode: OutputMode;
passwordStrength: {
guessesLog10: number;
entropyBits: number;
effectiveBits: number;
reason: string;
securityTier: 'strong' | 'moderate' | 'weak';
};
pq?: {
secretKey: FormattedKey; // { pem: string, raw: Uint8Array }
publicKey: FormattedKey;
keypair: SLHDSAKeypair;
};
legacy?: {
mnemonic: string; // 24-word BIP39 phrase
appPassword: string; // Base58 password
};
zero: () => void; // Call to zero sensitive buffers
}analyzePassword(password, userInputs?)
Analyze password strength.
interface PasswordAnalysis {
guessesLog10: number;
entropyBits: number;
penaltyShards: number;
reason: string;
isUnsafe: boolean;
securityTier: 'strong' | 'moderate' | 'weak';
}verifyFingerprint(config, expectedFingerprint, options?)
Verify credentials match expected fingerprint.
sign(message, secretKey) / verify(signature, message, publicKey)
SLH-DSA-SHAKE-256s signing and verification.
Acknowledgements
The concept of memory-hard brain wallets and the core algorithm design originated from Egor Homakov's work on XLN BrainVault.
This implementation:
- Adds post-quantum signatures (SLH-DSA-SHAKE-256s)
- Provides isomorphic browser/Node.js support
- Includes comprehensive CLI tooling
- Uses TypeScript with strict typing
License
MIT
