IPFS is public anyone who accidently gets the CID can retrieve the bytes. End-to-end encryption fixes this
Current state:
Files are uploaded to IPFS in plaintext.
Proposed implementation:
- On signup: generate an X25519 key pair client-side. Encrypt the private key with a key derived from the password (
PBKDF2 or Argon2id → AES-256-GCM). Store ciphertext + salt server-side under a fourth KV key "<user> IDENTITY".
- On login: server returns the encrypted identity. Frontend decrypts it in memory with the password. Drop password from memory.
- On upload: generate a random 256-bit DEK, encrypt the file with AES-256-GCM, push ciphertext to IPFS. Encrypt the DEK with the user's public key (sealed box via libsodium). Store wrapped DEK + nonce + tag in the node's
file_obj.
- On share: fetch recipient's public key, re-wrap the DEK with the recipient's public key, put the new wrapped DEK into the shared
Node copy.
- Use
libsodium.js / tweetnacl on the frontend, PyNaCl on the backend (only for recipient public-key lookup, not for private keys).
Files likely affected:
frontend/src/utils/crypto.js (new)
frontend/src/utils/api.js (upload/download flow changes)
backend/user_authentication_service.py (store encrypted identity)
backend/node.py / backend/file.py (carry wrapped DEK)
app.py
Acceptance criteria:
- A file uploaded by user A cannot be read by visiting the IPFS gateway directly.
- A file shared from A to B is decryptable by B and only B.
- Server operators (even with full DB access) cannot decrypt any file.
IPFS is public anyone who accidently gets the CID can retrieve the bytes. End-to-end encryption fixes this
Current state:
Files are uploaded to IPFS in plaintext.
Proposed implementation:
PBKDF2or Argon2id →AES-256-GCM). Store ciphertext + salt server-side under a fourth KV key"<user> IDENTITY".file_obj.Nodecopy.libsodium.js/tweetnaclon the frontend,PyNaClon the backend (only for recipient public-key lookup, not for private keys).Files likely affected:
frontend/src/utils/crypto.js(new)frontend/src/utils/api.js(upload/download flow changes)backend/user_authentication_service.py(store encrypted identity)backend/node.py/backend/file.py(carry wrapped DEK)app.pyAcceptance criteria: