GhostShard
GhostShard uses Shamir Secret Sharing to split the wallet seed into multiple shards, each stored in a different location. This eliminates single points of failure for seed backup.
How It Works
- The wallet seed is split into 5 shares with a threshold of 3 using Shamir's algorithm
- Each shard is assigned a storage type (DID, USB, password manager, email, cloud, device)
- A SHA-256 hash of each shard is registered on-chain in the
ShardRegistrycontract - To reconstruct the wallet, any 3 of the 5 shards are sufficient
Seed ──→ Shamir Split (5 shares, threshold 3)
├── Shard 1 → USB key
├── Shard 2 → Password manager
├── Shard 3 → DID document
├── Shard 4 → Encrypted email
└── Shard 5 → Device secure storage
Storage Types
| Type | Code | Description |
|---|---|---|
did | 1 | Decentralized identifier document |
usb | 2 | Physical USB security key |
pwd_mgr | 3 | Password manager (1Password, Bitwarden, etc.) |
email | 4 | Encrypted email to self |
cloud | 5 | Cloud storage (encrypted) |
device | 6 | Device secure storage (SecureEnclave / Keystore) |
Each storage type is encoded numerically for on-chain registration.
API
Splitting
const shardManager = new GhostShardManager();
const shards = await shardManager.splitSeed(seedHex);
// Returns Shard[]:
// {
// shardId: string (UUID),
// shardData: Uint8Array,
// storageType: ShardStorageType,
// hash: string (SHA-256)
// }
Assigning Storage
await shardManager.assignStorage(shardId, 'usb');
await shardManager.assignStorage(shardId, 'pwd_mgr');
Reconstruction
const seed = await shardManager.reconstructSeed([shard1, shard2, shard3]);
// Any 3 of 5 shards reconstruct the original seed
Verification
const isValid = await shardManager.verifyShard(shard);
// Recomputes SHA-256 and compares with stored hash
Memory Wipe
shardManager.clear();
// All shard data is overwritten with zeros before clearing
// shard.shardData.fill(0)
On-Chain Registry
The ShardRegistry Compact contract stores shard metadata on-chain:
Circuits:
- registerShard(walletId, shardId, shardHash, storageType)
- verifyShardHash(walletId, shardId, hash) — check if hash matches
- getShardCount(walletId) — number of registered shards
- getShardLocation(walletId, shardId) — storage type for a shard
- emergencyLock(walletId) — lock wallet, prevent new registrations
- isLocked(walletId) — check lock status
Emergency Lock: If a user suspects compromise, they can lock their wallet on-chain. This prevents new shard registrations and signals that existing shards should be treated as potentially compromised.
See ShardRegistry contract for the full API.
Mobile Integration
The GhostShard screen in the mobile app provides:
- Create Shards button — splits the current wallet seed into 5 shards
- Shard list — displays each shard with its storage type assignment
- Clear Shards — securely wipes all shard data from memory
The GhostContext exposes splitSeed(), shards, and clearShards() through the useGhost() hook.
Security Model
- Shards are never stored together — each goes to a different location
- The threshold (3) means losing up to 2 shards is recoverable
- On-chain hashes allow verification without revealing shard data
- Memory wipe (
Uint8Array.fill(0)) prevents residual data in RAM - The
secrets.js-34r7hlibrary implements Shamir's algorithm with cryptographic randomness