Skip to main content

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

  1. The wallet seed is split into 5 shares with a threshold of 3 using Shamir's algorithm
  2. Each shard is assigned a storage type (DID, USB, password manager, email, cloud, device)
  3. A SHA-256 hash of each shard is registered on-chain in the ShardRegistry contract
  4. 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

TypeCodeDescription
did1Decentralized identifier document
usb2Physical USB security key
pwd_mgr3Password manager (1Password, Bitwarden, etc.)
email4Encrypted email to self
cloud5Cloud storage (encrypted)
device6Device 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-34r7h library implements Shamir's algorithm with cryptographic randomness