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
This commit is contained in:
234
README.md
Normal file
234
README.md
Normal file
@@ -0,0 +1,234 @@
|
||||
# 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
|
||||
|
||||
```typescript
|
||||
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
|
||||
|
||||
```typescript
|
||||
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
|
||||
|
||||
```typescript
|
||||
// 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
|
||||
|
||||
```typescript
|
||||
// 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
|
||||
|
||||
```typescript
|
||||
interface UserIdentity {
|
||||
userId: string; // Hash of master public key
|
||||
publicKey: Uint8Array; // Master public key
|
||||
mnemonic?: string; // Recovery phrase
|
||||
}
|
||||
```
|
||||
|
||||
### DeviceIdentity
|
||||
|
||||
```typescript
|
||||
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
|
||||
|
||||
```typescript
|
||||
// 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
|
||||
Reference in New Issue
Block a user