Decentralized anti-ransomware backup system that encrypts your files, splits them across 5 storage nodes using erasure coding, and protects the encryption key with threshold cryptography. Even if 2 of 5 nodes go offline, your data is fully recoverable. Optionally anchors backup integrity to Bitcoin.
- AES-256-GCM encryption — files are encrypted with a random key before leaving your machine
- Reed-Solomon 3-of-5 erasure coding — encrypted data is split into 5 shards; any 3 reconstruct the original (1.67x storage overhead)
- Shamir's Secret Sharing 3-of-5 — the encryption key is split into 5 shares; any 3 reconstruct it
- L402 Lightning payments — data retrieval is gated by Lightning Network micropayments via the L402 protocol
- Bitcoin anchoring — backup state is committed to Bitcoin via OP_RETURN for tamper-evident integrity proof
- Proof-of-custody challenges — verify that storage nodes still hold your data without downloading it
- Real-time dashboard — web UI with live progress via Server-Sent Events
npm install
npm run start:dashboardOpen http://localhost:3000/dashboard
This starts the dashboard server on port 3000 and all 5 storage nodes on ports 3001-3005.
- Backup — encrypts, shards, and distributes your files across 5 nodes
- Simulate Attack — deletes your source files (ransomware simulation)
- Kill 2 Nodes — takes 40% of your storage infrastructure offline
- Restore — recovers all files from the remaining 3 nodes
- Kill a 3rd Node — restore now fails, proving the 3-of-5 threshold is real
- Verify Storage — sends proof-of-custody challenges to confirm nodes still hold data
# Start storage nodes manually
SKIP_L402=true npm run start:nodes
# Backup a directory
node src/client/backup.js --source <dir> --output ./backups
# Restore from manifest
node src/client/restore.js --manifest ./backups/<id>/manifest.json --output ./restored/<id>
# Run tests
node test/e2e.jsCLIENT (backup + restore CLI + dashboard)
|
| HTTP + L402
|
+---> Storage Node 1 (:3001) — shard 0 + key share 0
+---> Storage Node 2 (:3002) — shard 1 + key share 1
+---> Storage Node 3 (:3003) — shard 2 + key share 2
+---> Storage Node 4 (:3004) — shard 3 + key share 3
+---> Storage Node 5 (:3005) — shard 4 + key share 4
| Layer | Purpose | Technology | Overhead |
|---|---|---|---|
| Encryption | Confidentiality | AES-256-GCM | ~0% |
| Erasure Coding | Fault tolerance (data) | Reed-Solomon 3-of-5 | 1.67x |
| Secret Sharing | Fault tolerance (key) | Shamir 3-of-5 | 5x (but key is only 32 bytes) |
Backup: Source files -> tar archive -> AES-256-GCM encrypt -> Reed-Solomon encode (5 shards) -> Shamir split key (5 shares) -> distribute to nodes -> Merkle tree -> optional Bitcoin anchor -> write manifest
Restore: Load manifest -> fetch shards (L402 payment per shard) -> fetch key shares -> Reed-Solomon decode -> Shamir combine -> AES decrypt -> extract tar -> verify file hashes -> verify Bitcoin anchor
src/
core/ # Cryptographic modules
encrypt.js # AES-256-GCM encrypt/decrypt
erasure.js # Reed-Solomon 3-of-5 encode/decode
shamir.js # Shamir secret sharing split/combine
manifest.js # Backup manifest creation/validation
merkle.js # Merkle tree for Bitcoin anchoring
anchor.js # Bitcoin OP_RETURN anchoring via RPC
spotcheck.js # Proof-of-custody challenge generation
storage-node/
server.js # Express server (one per node)
store.js # Filesystem shard/keyshare storage
l402.js # L402 payment-gate middleware
client/
backup.js # Backup CLI
restore.js # Restore CLI
backup-pipeline.js # Backup async generator (shared by CLI + dashboard)
restore-pipeline.js # Restore async generator (shared by CLI + dashboard)
lightning.js # LNbits payment helper
dashboard/
server.js # Dashboard server (port 3000, manages nodes)
index.html # Single-page dashboard
app.js # Dashboard interactive logic
styles.css # Dark theme styling
config/
nodes.json # Storage node URLs and ports
lightning.json # LNbits connection details
bitcoin.json # Bitcoin Core RPC config (for anchoring)
test/
e2e.js # End-to-end test (15 steps)
Set SKIP_L402=true to bypass Lightning payment gating:
SKIP_L402=true npm run start:nodesThe dashboard (npm run start:dashboard) uses SKIP_L402 automatically. All backup/restore operations work identically — payment is simply skipped.
To enable L402 payments:
- Install Polar and LNbits
- Create a Polar network with 6 LND nodes (
client+storage-1throughstorage-5) and 1 Bitcoin Core backend - Start the network, mine blocks, open channels from client to each storage node
- Connect LNbits to one LND node, create 6 wallets
- Fill in
config/lightning.jsonwith the API keys
Every backup snapshot can be cryptographically anchored to Bitcoin via OP_RETURN:
- A Merkle tree is built from all file hashes, shard hashes, key hash, and archive hash
- The 32-byte Merkle root is embedded in a Bitcoin transaction
- During restore, the root is recomputed and verified against the on-chain commitment
To enable:
- In Polar, note the Bitcoin Core RPC credentials
- Fill in
config/bitcoin.jsonwithrpcUrl,rpcUser,rpcPass,wallet - Anchoring runs automatically during backup; skips gracefully if Bitcoin Core is unavailable
# Unit tests
node src/core/__tests__/encrypt.test.js
node src/core/__tests__/erasure.test.js
node src/core/__tests__/shamir.test.js
node src/core/__tests__/manifest.test.js
node src/core/__tests__/pipeline.test.js
node src/core/__tests__/merkle.test.js
node src/core/__tests__/spotcheck.test.js
node src/storage-node/__tests__/store.test.js
node src/storage-node/__tests__/l402.test.js
node src/client/__tests__/lightning.test.js
node src/core/__tests__/anchor.test.js # requires Polar
# End-to-end test (starts nodes, full backup/restore cycle, fault tolerance)
node test/e2e.js- Runtime: Node.js 18+ (ESM)
- Server: Express
- Encryption: Node.js built-in
crypto(AES-256-GCM, SHA-256) - Erasure coding:
@subspace/reed-solomon-erasure.wasm - Secret sharing:
shamir-secret-sharing - L402:
macaroon+ LNbits REST API - Bitcoin: Native
fetchwith JSON-RPC (no additional dependencies) - Dashboard: Plain HTML/CSS/JS (no framework)
- The manifest is NOT secret but IS critical — without it, recovery is impossible
- Key shares are stored in plaintext on disk in this MVP; production would encrypt them
- No TLS between client and nodes — everything is localhost HTTP; production requires TLS
- No authentication on upload endpoints — production requires auth
- The OP_RETURN anchor contains only a Merkle root hash — zero information about backup contents is leaked on-chain
ISC