npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

branevault

v1.0.7

Published

Memory-hard deterministic key derivation from human-memorable credentials

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. This is v1.0.0 - first public release. 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:

  1. Generate keys and save receipt
  2. Verify you can reproduce the fingerprint 5-10 times over several days
  3. Start with small test amounts ($10-100)
  4. Only increase amounts after successful recall testing

What It Does

BrainVault derives deterministic post-quantum cryptographic keys from:

  • An identity (email/username)
  • A master password
  • Configurable security parameters

It outputs:

  • A SLH-DSA-SHAKE-256s keypair (NIST FIPS 205, post-quantum secure)
  • A high-entropy Base58 password (for legacy applications)
  • A 24-word BIP39 mnemonic (optional, for existing cryptocurrency infrastructure)

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 dependency
npm install brainvault

CLI Usage

Generate Keys

# Interactive mode
npx brainvault

# With receipt (re-hydrates previous settings)
npx brainvault --receipt ./my-receipt.json

Verify Credentials

# Verify you can reproduce the same fingerprint
npx brainvault-verify ./my-receipt.json

# Manual parameter entry
npx brainvault-verify --manual

Programmatic Usage

import { deriveKeys, createConfig, Profile } from 'brainvault';

const config = createConfig({
  identity: '[email protected]',
  password: Buffer.from('my-secure-password'),
  profile: Profile.Standard,
  generation: 0,
  factor: 3,
  outputMode: 'pq',  // 'pq' | 'legacy' | 'both'
});

const result = await deriveKeys(config, {
  onProgress: (current, total) => {
    console.log(`Progress: ${current}/${total}`);
  },
});

// Post-quantum keys (primary output)
console.log(result.pq.secretKey);   // 128-byte SLH-DSA secret key
console.log(result.pq.publicKey);   // 64-byte SLH-DSA public key

// Legacy outputs (when outputMode is 'legacy' or 'both')
console.log(result.legacy?.mnemonic);     // 24-word BIP39 phrase
console.log(result.legacy?.appPassword);  // Base58 password

console.log(result.fingerprint);   // 12-char verification fingerprint

// IMPORTANT: Zero sensitive buffers when done
result.zero();

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 email hash (for verification)
  • Profile, generation, factor settings
  • Fingerprint (for credential recall testing)
  • NO secrets

Use receipts to:

  1. Re-hydrate settings on future runs
  2. Verify you remember credentials correctly
  3. Document your setup (store separately from passwords)

Algorithm Details

1. Salt = SHA3-256(emailHash | shardIndex | generation | ALG_TAG)
2. For each shard i in [0, totalShards):
     shardOutput[i] = Argon2id(password, salt_i, memCost, timeCost=2, parallelism)
3. masterIKM = SHA3-512(header | shard[0] | shard[1] | ... | shard[n])
4. slhDsaSeed = HKDF-SHA512(masterIKM, context="BrainVault-v3-SLH-DSA-SHAKE-256s-Seed", 96 bytes)
5. (secretKey, publicKey) = SLH-DSA-SHAKE-256s-KeyGen(slhDsaSeed)
6. [Optional] mnemonicEntropy = HKDF-SHA512(masterIKM, context="BrainVault-v3-BIP39-Mnemonic", 32 bytes)
7. [Optional] passwordEntropy = HKDF-SHA512(masterIKM, context="BrainVault-v3-Base58-Password", 64 bytes)

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:

  • zeroBuffer() calls buf.fill(0) but V8 may retain copies in memory
  • Garbage collection timing is unpredictable
  • Old buffer contents may persist in heap memory after cleanup
  • String passwords are interned by JavaScript and cannot be zeroed
  • Hot-path JIT optimizations may create additional copies

Mitigation: Reboot the machine after key generation to clear RAM. Use air-gapped dedicated hardware.

Beta Software (v1.0.0)

This is the first public release. Treat it as beta:

  • Start with small test amounts - Send $10-100 maximum until community review
  • Test credential recall BEFORE funding - Verify you can reproduce fingerprint multiple times
  • Wait for professional audit before using for significant amounts
  • Report issues at github.com/adimov-eth/brainvault

What Could Go Wrong

| Risk | Impact | Mitigation | |------|--------|------------| | Password forgotten | Total fund loss | Use memorable passphrase, test recall extensively before funding | | Unicode normalization bug | Wrong keys derived | Now mitigated via NFC normalization, but test on your actual OS/keyboard | | @noble/post-quantum bug | Key compromise | Wait for audit, use small amounts only | | Air-gap violated | Key theft | Dedicated offline machine, never connect to network | | Receipt lost | Cannot verify settings | Can re-derive if you remember all parameters, back up receipt securely | | JavaScript memory leak | Sensitive data exposure | Reboot after generation, use dedicated hardware | | Implementation bug | Incorrect keys/loss | Test with small amounts first, wait for community review |

Recommended Usage

  1. Test phase (current):

    • Generate keys on air-gapped machine
    • Send small test amount ($10-100)
    • Practice credential recall 5-10 times over several days
    • Verify fingerprint matches receipt each time
    • Only increase amount after successful recall testing
  2. Production phase (after audit):

    • Commission independent security audit
    • Verify audit findings
    • Use bunker profile on dedicated hardware
    • Consider multi-signature schemes for large amounts

Security Considerations

  1. Air-gap is mandatory - Never run on networked machines. Compromised keys mean lost funds.
  2. Password entropy matters - Memory-hardness helps but doesn't fix weak passwords. Use 20+ character passphrases with mixed character types.
  3. Test recall before funding - Verify you can reproduce the exact fingerprint multiple times over several days before sending any funds.
  4. Receipts are not secrets - But store them separately from passwords. Loss means you need to remember all parameters manually.
  5. Generation for rotation - Increment generation parameter if you suspect compromise.
  6. Buffer zeroing is best-effort - JavaScript/V8 GC limitations mean sensitive data may persist. Reboot after generation.

API Reference

deriveKeys(config, options?)

Main derivation function.

interface DerivationConfig {
  identity: string;
  password: Buffer;
  profile: Profile;
  generation: number;
  factor: number;
  outputMode: 'pq' | 'legacy' | 'both';
}

interface DerivationOptions {
  onProgress?: (current: number, total: number) => void;
}

interface DerivationResult {
  pq?: {
    secretKey: Buffer;   // 128 bytes
    publicKey: Buffer;   // 64 bytes
    keypair: Buffer;     // 192 bytes (concatenated)
  };
  legacy?: {
    mnemonic: string;      // 24-word BIP39 phrase
    appPassword: string;   // Base58 password
  };
  fingerprint: string;
  totalShards: number;
  zero: () => void;  // Call to zero internal buffers
}

analyzePassword(password, userInputs?)

Analyze password strength.

interface PasswordAnalysis {
  guessesLog10: number;
  penaltyShards: number;
  reason: string;
  isUnsafe: boolean;
}

verifyFingerprint(config, expectedFingerprint, options?)

Verify credentials match expected fingerprint.

interface VerificationResult {
  matches: boolean;
  computedFingerprint: string;
  expectedFingerprint: string;
}

License

MIT