Skip to content

Conversation

@sirtimid
Copy link
Contributor

@sirtimid sirtimid commented Jan 27, 2026

Closes #778

Summary

Implements BIP39 mnemonic phrase support for kernel identity seed recovery, addressing #778.

Changes:

  • Add @scure/bip39 dependency (audited, secure BIP39 implementation)
  • Add generateMnemonic() to create new random mnemonics (12 or 24 words)
  • Add isValidMnemonic() to validate BIP39 mnemonic phrases
  • Add mnemonicToSeed() to derive a 32-byte seed using standard PBKDF2 derivation
  • Add mnemonic option to Kernel.make() (recommended) and initRemoteComms()
  • Throw error when mnemonic conflicts with existing identity (use resetStorage: true)
  • Export new utility functions from package index

Usage:

import { generateMnemonic, Kernel } from '@metamask/ocap-kernel';

// Generate mnemonic for user to backup
const mnemonic = generateMnemonic();

// Initialize kernel with mnemonic
const kernel = await Kernel.make(platformServices, db, { mnemonic });
await kernel.initRemoteComms({ relays });

// Recovery: use same mnemonic on new device
const kernel = await Kernel.make(platformServices, db, {
  resetStorage: true,
  mnemonic: 'user provided recovery phrase...',
});

Implementation Notes

  • Uses standard BIP39 PBKDF2-HMAC-SHA512 derivation (2048 iterations) for cryptographic soundness
  • Supports all valid BIP39 mnemonic lengths (12, 15, 18, 21, 24 words)
  • PBKDF2 is one-way, so users must generate and store mnemonic first if they want backup capability
  • Random seeds (default when no mnemonic provided) cannot be backed up as mnemonics

Acceptance Criteria from Issue

  • BIP39 mnemonic accepted for seed generation
  • Same mnemonic always produces same peer ID
  • Existing random seed generation still works (backward compatible)
  • Mnemonic validation (checksum verification)
  • Unit tests for mnemonic-based key derivation
  • Documentation for backup/recovery procedures

Test plan

  • Unit tests for generateMnemonic() - generates valid 12/24-word mnemonics
  • Unit tests for isValidMnemonic() - validates all BIP39 lengths, rejects invalid checksums
  • Unit tests for mnemonicToSeed() - deterministic PBKDF2 conversion, test vector verification
  • Unit tests for initRemoteComms with mnemonic option - seed derivation, peer ID consistency
  • Unit tests for error when mnemonic conflicts with existing identity
  • E2E tests for identity recovery scenarios

🤖 Generated with Claude Code


Note

Adds recoverable kernel identities via BIP39 mnemonics and integrates them into initialization flows.

  • New utils: generateMnemonic(), isValidMnemonic(), mnemonicToSeed() (exported from index.ts) using @scure/bip39
  • Kernel.make and initRemoteComms accept optional mnemonic; initRemoteComms derives keySeed from it and logs usage
  • Conflict handling: providing mnemonic when an identity exists throws a clear error; resetStorage: true enables recovery; initRemoteComms option takes precedence over constructor
  • RemoteManager plumbs mnemonic; remote-comms.ts supports mnemonic-based seed derivation and preserves known relays behavior
  • Docs: new docs/identity-backup-recovery.md; docs/usage.md updated with quick-start and link
  • Tests: comprehensive unit tests for BIP39 utils and remote-comms mnemonic paths; Node E2E tests verify peer ID stability, conflicts, invalid mnemonics, and recovery
  • Package changes: add @scure/bip39 dependency; adjust public exports and expected exports test

Written by Cursor Bugbot for commit f27b0e4. This will update automatically on new commits. Configure here.

@socket-security
Copy link

socket-security bot commented Jan 27, 2026

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Added@​scure/​bip39@​2.0.110010010082100

View full report

@github-actions
Copy link
Contributor

github-actions bot commented Jan 27, 2026

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 88.43%
⬇️ -0.01%
5779 / 6535
🔵 Statements 88.31%
⬇️ -0.01%
5871 / 6648
🔵 Functions 87.26%
⬆️ +0.03%
1507 / 1727
🔵 Branches 84.96%
⬆️ +0.01%
2086 / 2455
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
packages/ocap-kernel/src/Kernel.ts 91.13%
⬇️ -3.53%
83.33%
⬇️ -4.17%
92.3%
🟰 ±0%
91.13%
⬇️ -3.53%
113-115, 120, 229-232, 414, 484
packages/ocap-kernel/src/index.ts 100%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
packages/ocap-kernel/src/remotes/types.ts 100%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
packages/ocap-kernel/src/remotes/kernel/RemoteManager.ts 98.27%
⬆️ +0.06%
100%
🟰 ±0%
100%
🟰 ±0%
98.27%
⬆️ +0.06%
125
packages/ocap-kernel/src/remotes/kernel/remote-comms.ts 100%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
packages/ocap-kernel/src/utils/bip39.ts 100% 100% 100% 100%
Generated in workflow #3381 for commit f27b0e4 by the Vitest Coverage Report Action

@sirtimid sirtimid marked this pull request as ready for review January 27, 2026 22:07
@sirtimid sirtimid requested a review from a team as a code owner January 27, 2026 22:07
Copy link
Contributor

@grypez grypez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Early review to keep up with the PR.

@sirtimid sirtimid force-pushed the sirtimid/bip39-seed-recovery branch from 5e68dcc to 0222bc0 Compare January 27, 2026 23:32
sirtimid and others added 12 commits January 28, 2026 00:40
Add @scure/bip39 for BIP39 mnemonic phrase support in kernel identity
seed recovery.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add BIP39 mnemonic phrase support for kernel identity seed recovery:

- Add isValidMnemonic() to validate BIP39 mnemonic phrases
- Add mnemonicToSeed() to derive a 32-byte seed from a mnemonic
- Add seedToMnemonic() to export a seed as a 12-word mnemonic
- Extend RemoteCommsOptions with optional 'mnemonic' parameter
- Update initRemoteComms to use mnemonic for seed derivation when provided
- Export new utility functions from package index

This enables users to backup and recover their kernel identity using
a standard BIP39 mnemonic phrase. The same mnemonic will always produce
the same peer ID, allowing identity recovery on new hosts.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add unit tests for the new BIP39 mnemonic functionality:

- isValidMnemonic: validation of 12/24-word mnemonics, checksums, and edge cases
- mnemonicToSeed: conversion, determinism, and error handling
- seedToMnemonic: conversion and round-trip validation
- initRemoteComms with mnemonic option: seed derivation, peer ID consistency,
  existing identity preservation, and error cases

Also fix seedToMnemonic to validate hex string length before conversion.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add end-to-end tests for the BIP39 mnemonic functionality:

- BIP39 Utility Functions tests: validation, seed conversion, round-trip
- BIP39 Identity Recovery tests:
  - Same mnemonic produces same peer ID (deterministic)
  - Different mnemonic produces different peer ID
  - Existing identity is preserved (mnemonic ignored)
  - Invalid mnemonic throws error

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add comprehensive documentation for BIP39 mnemonic-based identity
backup and recovery:

- Create docs/identity-backup-recovery.md with:
  - Overview of kernel identity and BIP39 support
  - API reference for utility functions
  - Usage scenarios (first-time setup, backup, recovery, verification)
  - Security best practices
  - Error handling examples

- Update docs/usage.md with:
  - Add Identity Backup and Recovery to table of contents
  - Add brief section with link to the detailed guide

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Move BIP39 mnemonic utilities from remote-comms.ts to a dedicated
utils/bip39.ts module for better separation of concerns:

- Create src/utils/bip39.ts with isValidMnemonic, mnemonicToSeed,
  seedToMnemonic functions
- Create src/utils/bip39.test.ts with unit tests for the utilities
- Update remote-comms.ts to import mnemonicToSeed from utils
- Update index.ts to export from utils/bip39.ts
- Remove duplicate BIP39 utility tests from remote-comms.test.ts

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…eeds

- Replace non-standard entropy doubling with proper PBKDF2-HMAC-SHA512
- Remove seedToMnemonic (PBKDF2 is one-way, cannot reverse)
- Add generateMnemonic for creating new random mnemonics
- Support all valid BIP39 mnemonic lengths (12, 15, 18, 21, 24 words)
- Add test vector verification for standard BIP39 compliance
- Update documentation to reflect new backup/recovery workflow

BREAKING: Users must now generate a mnemonic first if they want
backup capability. Random seeds cannot be backed up as mnemonics.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Allow passing mnemonic directly to Kernel.make for cleaner API:

  const kernel = await Kernel.make(platformServices, db, { mnemonic });
  await kernel.initRemoteComms({ relays });

The mnemonic can still be passed to initRemoteComms for backwards
compatibility, and takes precedence if provided in both places.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…dentity

Instead of silently ignoring the mnemonic parameter when an identity
already exists, throw an error to prevent using a different identity
than expected. Users must use resetStorage: true to clear existing
identity before using a mnemonic for recovery.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The resetStorage option preserves identity fields by design. When
combined with mnemonic for recovery, also clear identity fields
so the new mnemonic can be used.

Adds test to verify the recovery workflow works correctly.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove reference to non-existent seedToMnemonic function in usage.md
- Update example to show correct workflow: generate mnemonic first, then
  use for initialization and recovery
- Fix RemoteCommsOptions.mnemonic JSDoc to clarify that an error is thrown
  when identity exists, not silently ignored

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@sirtimid sirtimid force-pushed the sirtimid/bip39-seed-recovery branch from d212604 to f27b0e4 Compare January 27, 2026 23:40
@sirtimid sirtimid requested a review from grypez January 27, 2026 23:41
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

this.#kernelStore.kv.delete('keySeed');
this.#kernelStore.kv.delete('peerId');
this.#kernelStore.kv.delete('ocapURLKey');
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Invalid mnemonic causes irreversible identity loss before validation

High Severity

When resetStorage: true and mnemonic are provided to Kernel.make(), the identity keys (keySeed, peerId, ocapURLKey) are deleted immediately based only on whether options.mnemonic is truthy. The mnemonic is only validated later in initRemoteComms() when mnemonicToSeed() is called. If the mnemonic is invalid (typo, wrong checksum, etc.), the user's original identity is already irreversibly deleted, and the kernel cannot proceed with the invalid mnemonic either, resulting in data loss.

Fix in Cursor Fix in Web

Copy link
Contributor

@grypez grypez Jan 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting enough to punt to the backlog, but not really in the kernel's contract.

@sirtimid sirtimid added this pull request to the merge queue Jan 28, 2026
Merged via the queue into main with commit 97b3c8b Jan 28, 2026
34 checks passed
@sirtimid sirtimid deleted the sirtimid/bip39-seed-recovery branch January 28, 2026 09:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Remote comms: BIP39 seed recovery for kernel identity

3 participants