# 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:
> 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 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

```bash
# Global installation (for CLI)
npm install -g brainvault

# Or run directly with npx
npx brainvault

# As a library
npm install brainvault
```

## CLI Usage

### Generate Keys

```bash
# Interactive mode
npx brainvault

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

### Verify Credentials

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

# Manual parameter entry
npx brainvault-verify --manual
```

## Library Usage

```typescript
import { deriveKeys, createConfig, Profile, OutputMode } from 'brainvault';

const config = createConfig({
  identity: 'user@example.com',
  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:

```typescript
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:
1. Re-hydrate settings on future runs
2. Verify you remember credentials correctly
3. 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](./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](https://github.com/paulmillr/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.

```typescript
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.

```typescript
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.

```typescript
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](https://github.com/homakov)'s work on [XLN BrainVault](https://github.com/xlnfinance/xln/blob/main/.archive/brainvault/brainvault.js).

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
