We were assuming that all nodes are trusted for now...
But we anyone knowing the chunkKey can come and request for deletion via tombstone or pollute the routing table.
Data plane is robust but the control plane is not that secure.
IN-DEPTH ANALYSIS: what if a node in the network is hijacked?
What a Hijacked Node CANNOT Do
These are already defended by the existing code:
1. Serve you corrupted chunks ✅ Blocked
This is the most important one. verifyChunkHash() in chunked_ops.go:
func verifyChunkHash(expectedKey string, data []byte) error {
actual := sha256.Sum256(data)
actualHex := hex.EncodeToString(actual[:])
if actualHex != expectedKey {
return fmt.Errorf("chunk integrity failed: expected %s, got %s", ...)
}
return nil
}
A hijacked node sends you garbage bytes claiming they're chunk "a3f9...". Your node computes SHA256(garbage) = "zz11..." — doesn't match — rejected before hitting disk. This is the core power of content-addressing. The hash IS the trust.
2. Overwrite an existing chunk ✅ Impossible
The chunk key is the SHA-256 of the content. To overwrite chunk "a3f9..." with malicious data, the attacker would need to find data whose SHA-256 is also "a3f9..." — that's a SHA-256 preimage attack, computationally infeasible.
3. Read your files ✅ Blocked by encryption
Even if the hijacked node has all your chunks, they're ChaCha20-Poly1305 ciphertext. Useless without myKey.key, which never leaves your machine.
4. Fake/modify a manifest ✅ Blocked
The manifest is stored under CID + ".manifest", where CID = SHA256(entire encrypted content). A fake manifest would produce a different CID — it can't silently replace yours.
What a Hijacked Node CAN Do
These are real threats with no current defense:
1. ❌ Issue fake tombstones (when deletion is added)
This is exactly the auth problem from before. Without signatures, a hijacked node can broadcast MessageDeleteFile{CID: yourCID} and every peer will comply.
Fix: Ed25519 signatures on tombstones — only the key that produced chunkKey can sign the deletion.
2. ❌ Eclipse attack — poison your routing table
The hijacked node sends MessageFindNodeResponse or MessagePeerExchange filled with fake/attacker-controlled addresses. Your DHT routing table fills with malicious nodes. Now all your chunk requests go to the attacker.
// attacker's PeerExchange — shares only their own fake nodes
KnownPeers: []PeerInfo{
{ID: fakeID1, Addr: "attacker1:7000"},
{ID: fakeID2, Addr: "attacker2:7000"},
// ... 20 more attacker nodes
}
Now DHT.NearestNodes() returns only attacker nodes for every lookup.
Fix: Enforce routing table diversity — cap how many entries from a single /24 subnet, validate that peers are actually reachable before trusting them.
3. ❌ Sybil attack — fake many node identities
Node IDs in this system are just SHA256(arbitraryString). Generate a million IDs, flood the routing table.
// nothing stops this:
nodeID, _ = server.LoadOrGenerateNodeID(dataDir) // just a random hex string
Fix: Proof-of-work on node IDs (generate IDs whose hash has N leading zeros) or a trusted identity registry.
4. ❌ Selective refusal (selfish node)
Just never respond to MessageGetChunk for your files. No timeout, no retry-from-different-node logic. Your fetchSingleChunk waits 5 seconds and gives up:
case <-timer.C:
fmt.Printf("WARNING: chunk %s not received after 5s timeout\n", ...)
No fallback to a different peer — the fetch just fails.
Fix: On timeout, explicitly try the next DHT-nearest node instead of giving up.
5. ❌ Store garbage to fill DHT space near your file
An attacker generates keys close to your CID in the DHT keyspace (feasible to brute-force since IDs are just SHA-256 of arbitrary strings). They become "K-nearest" to your file and when you replicate — your chunks go to them. They store or discard as they please.
The Core Security Model
Trust model today:
┌─────────────────────────────────────────────────┐
│ Transport layer → encrypted (X25519 AEAD) │
│ Chunk content → hash-verified │
│ File plaintext → encrypted (user key) │
│ │
│ Routing / Discovery → ⚠️ TRUSTED │
│ Tombstone/deletion → ⚠️ TRUSTED │
│ Node identity → ⚠️ TRUSTED │
└─────────────────────────────────────────────────┘
The data plane (chunks, encryption) is actually quite robust. The control plane (who routes where, who gets to delete, who counts as a valid node) has zero adversarial hardening.
This is normal for this stage of a DFS project — BitTorrent had the same shape for years before DHT was hardened against Sybil attacks. The honest answer is:
This system is designed for trusted-node networks (your own machines, friends, a private cluster). For an open public internet deployment where any stranger can join, the control plane needs significant hardening before you'd want to rely on it.
We were assuming that all nodes are trusted for now...
But we anyone knowing the chunkKey can come and request for deletion via tombstone or pollute the routing table.
Data plane is robust but the control plane is not that secure.
IN-DEPTH ANALYSIS: what if a node in the network is hijacked?
What a Hijacked Node CANNOT Do
These are already defended by the existing code:
1. Serve you corrupted chunks ✅ Blocked
This is the most important one. verifyChunkHash() in chunked_ops.go:
A hijacked node sends you garbage bytes claiming they're chunk
"a3f9...". Your node computesSHA256(garbage) = "zz11..."— doesn't match — rejected before hitting disk. This is the core power of content-addressing. The hash IS the trust.2. Overwrite an existing chunk ✅ Impossible
The chunk key is the SHA-256 of the content. To overwrite chunk
"a3f9..."with malicious data, the attacker would need to find data whose SHA-256 is also"a3f9..."— that's a SHA-256 preimage attack, computationally infeasible.3. Read your files ✅ Blocked by encryption
Even if the hijacked node has all your chunks, they're ChaCha20-Poly1305 ciphertext. Useless without myKey.key, which never leaves your machine.
4. Fake/modify a manifest ✅ Blocked
The manifest is stored under
CID + ".manifest", whereCID = SHA256(entire encrypted content). A fake manifest would produce a different CID — it can't silently replace yours.What a Hijacked Node CAN Do
These are real threats with no current defense:
1. ❌ Issue fake tombstones (when deletion is added)
This is exactly the auth problem from before. Without signatures, a hijacked node can broadcast
MessageDeleteFile{CID: yourCID}and every peer will comply.Fix: Ed25519 signatures on tombstones — only the key that produced
chunkKeycan sign the deletion.2. ❌ Eclipse attack — poison your routing table
The hijacked node sends MessageFindNodeResponse or MessagePeerExchange filled with fake/attacker-controlled addresses. Your DHT routing table fills with malicious nodes. Now all your chunk requests go to the attacker.
Now
DHT.NearestNodes()returns only attacker nodes for every lookup.Fix: Enforce routing table diversity — cap how many entries from a single
/24subnet, validate that peers are actually reachable before trusting them.3. ❌ Sybil attack — fake many node identities
Node IDs in this system are just
SHA256(arbitraryString). Generate a million IDs, flood the routing table.Fix: Proof-of-work on node IDs (generate IDs whose hash has N leading zeros) or a trusted identity registry.
4. ❌ Selective refusal (selfish node)
Just never respond to MessageGetChunk for your files. No timeout, no retry-from-different-node logic. Your fetchSingleChunk waits 5 seconds and gives up:
No fallback to a different peer — the fetch just fails.
Fix: On timeout, explicitly try the next DHT-nearest node instead of giving up.
5. ❌ Store garbage to fill DHT space near your file
An attacker generates keys close to your CID in the DHT keyspace (feasible to brute-force since IDs are just SHA-256 of arbitrary strings). They become "K-nearest" to your file and when you replicate — your chunks go to them. They store or discard as they please.
The Core Security Model
The data plane (chunks, encryption) is actually quite robust. The control plane (who routes where, who gets to delete, who counts as a valid node) has zero adversarial hardening.
This is normal for this stage of a DFS project — BitTorrent had the same shape for years before DHT was hardened against Sybil attacks. The honest answer is: