Files
identity/README.md
Chris Daßler a6b10428fa Initial commit: Identity management component
- Hierarchical user/device identity system with HD key derivation
- Dependency injection for AsyncStorage and Platform
- Self-contained TypeScript declarations
- Ed25519 keypairs managed by IdentityManager
- Deterministic peer ID generation from BIP39 mnemonic
2025-08-29 14:17:39 +02:00

7.5 KiB

Identity Management Component v1.0.0

Hierarchical user/device identity management system with HD key derivation for multi-device support.

Features

  • HD Key Derivation: Uses BIP39 mnemonics and BIP32 HD wallets
  • User/Device Hierarchy: Master user identity with derived device identities
  • Deterministic Peer IDs: Generates standard libp2p peer IDs (12D3KooW format) from HD keys
  • Secure Storage: Persistent storage with AsyncStorage adapter
  • Device Management: Add, remove, and list devices with unique indices
  • Recovery: 24-word mnemonic phrase for backup/restore
  • libp2p Compatible: Generates Ed25519 keypairs and standard peer IDs
  • Verifiable Identity: Peer IDs can be cryptographically verified as belonging to a user

Usage

Basic Usage

import { identityManager } from '@/components/identity/1.0.0';

// Initialize identity (creates new or loads existing)
const userIdentity = await identityManager.initialize();
console.log('User ID:', userIdentity.userId);

// Get current device
const device = await identityManager.getCurrentDevice();
console.log('Device ID:', device.deviceId);

// Get libp2p keypair
const keypair = await identityManager.getLibp2pKeypair();

Advanced Usage with Dependency Injection

import { 
  createIdentityManager, 
  IdentityConfig 
} from '@/components/identity/1.0.0';

const config: IdentityConfig = {
  storagePrefix: '@MyApp',
  mnemonicStrength: 256,
  deviceNameProvider: async () => 'Custom Device Name'
};

const identityManager = createIdentityManager(config);

Device Management

// Create new device identity (auto-increments index)
const newDevice = await identityManager.createDeviceIdentity('Tablet');
console.log('New device peer ID:', newDevice.deviceId); // 12D3KooW...

// List all devices
const devices = await identityManager.getRegisteredDevices();

// Remove a device
await identityManager.removeDevice(deviceId);

// Verify a peer belongs to this user
const peerBelongsToUser = await identityManager.verifyPeerOwnership(peerId);

Backup and Recovery

// Get recovery phrase
const mnemonic = identityManager.getMnemonic();

// Restore from mnemonic (maintains device index coordination)
await identityManager.restoreFromMnemonic(mnemonic);

// After restoration, device gets next available index
const device = await identityManager.getCurrentDevice();
console.log('Device index:', device.derivationPath); // e.g., m/44'/0'/0'/0/1

Interfaces

IIdentityManager

Main interface for identity management operations.

UserIdentity

interface UserIdentity {
  userId: string;           // Hash of master public key
  publicKey: Uint8Array;    // Master public key
  mnemonic?: string;        // Recovery phrase
}

DeviceIdentity

interface DeviceIdentity {
  deviceId: string;         // libp2p peer ID (12D3KooW... format)
  deviceName: string;       // Human-readable name
  publicKey: Uint8Array;    // Ed25519 public key
  privateKey: Uint8Array;   // Ed25519 private key (seed)
  derivationPath: string;   // HD derivation path (m/44'/0'/0'/0/index)
  createdAt: number;
  lastSeen?: number;
}

Architecture

┌─────────────────────────────────┐
│     IdentityFactory             │
│   (Singleton Factory)            │
└─────────────┬───────────────────┘
              │
              ▼
┌─────────────────────────────────┐
│     IdentityManager              │
│   (Core Implementation)          │
└─────────────┬───────────────────┘
              │
              ▼
┌─────────────────────────────────┐
│    AsyncStorageAdapter           │
│   (Persistence Layer)            │
└─────────────────────────────────┘

HD Key Derivation Path

The component uses BIP44-like derivation paths:

m/44'/0'/0'/0/[device_index]
  • 44': Purpose (identity management)
  • 0': Coin type (custom for this app)
  • 0': Account (always 0 for now)
  • 0: External chain
  • [device_index]: Sequential device index (0, 1, 2, ...)

Each device gets a unique index, ensuring unique peer IDs while maintaining the cryptographic relationship to the user identity.

Peer ID Generation

The system generates standard libp2p peer IDs from Ed25519 keys:

  1. Derive Ed25519 keypair from HD path
  2. Add multicodec prefix (0xed01) to public key
  3. Hash with SHA256 for standard format
  4. Encode as base58 with multihash prefix (0x12)
  5. Result: Peer IDs starting with 12D3KooW...

This ensures compatibility with all libp2p implementations while maintaining deterministic generation from the mnemonic.

Device Index Coordination

During device pairing:

  1. Master device tracks the highest device index
  2. New device receives its assigned index during pairing
  3. Storage key: identity_<userId>_highestDeviceIndex
  4. Fallback: System can detect existing indices by testing derivations

This prevents peer ID collisions when multiple devices join the same identity.

Security Considerations

  1. Mnemonic Storage: The mnemonic is stored in AsyncStorage. In production, consider encrypting it.
  2. Private Keys: Device private keys are stored locally. Use secure storage in production.
  3. Recovery Phrase: Users should backup their recovery phrase securely.
  4. Device Removal: Removing a device only removes it from the registry, not from the device itself.
  5. Peer ID Verification: Any peer ID can be verified as belonging to a user by testing derivation paths.
  6. Deterministic Generation: Lost devices can be recovered with the same peer ID using mnemonic + index.

DHT Integration

The identity system integrates with the DHT for user/device discovery:

  1. User identity is registered with the DHT
  2. Each device is registered under the user
  3. DHT tracks online/offline status of devices
  4. Enables device handoff and multi-device sync

Peer ID Update Broadcasting

When a device's peer ID changes (typically after pairing and identity restoration), the system automatically notifies other devices:

How It Works

  1. Detection: System detects peer ID change after restoreFromMnemonic()
  2. Broadcast: Sends update notification via /metatrom/identity/peer-update/1.0.0 protocol
  3. Update: Other devices update their records automatically
  4. Migration: Chat messages and connections migrate to new peer ID

Usage

// Automatic during pairing
const oldPeerId = await identityManager.getCurrentDevice()?.deviceId;
await identityManager.restoreFromMnemonic(mnemonic);
const newPeerId = await identityManager.getCurrentDevice()?.deviceId;

// Broadcast if changed (automatic in pairing flow)
if (oldPeerId !== newPeerId) {
  await identityManager.broadcastPeerIdUpdate(
    oldPeerId,
    newPeerId,
    sendProtocolData
  );
}

Benefits

  • Seamless Updates: No manual intervention needed
  • Preserves History: Chat and connection history maintained
  • Prevents Duplicates: Eliminates duplicate peer ID issues
  • Network Coherence: All devices stay synchronized

Version

  • Component Version: 1.0.0
  • Protocol Version: /metatrom/identity/1.0.0

License

MIT