सामग्री पर जाएँ
HexaTransfer
ब्लॉग पर वापस
तकनीकी गहन विश्लेषण

Build an Encrypted फ़ाइल शेयरिंग App from Scratch

Step-by-step tutorial to build an encrypted फ़ाइल शेयरिंग application. Frontend एन्क्रिप्शन, सुरक्षित backend, and deployment walkthrough.

एक encrypted file sharing app बनाने का मतलब है crypto को browser में डालना, server में नहीं। एक minimal stack इस तरह दिखता है: एक Vite-powered React frontend जो Web Crypto API के माध्यम से AES-256-GCM से encrypt करता है, एक Fastify backend जो हर upload को opaque blob मानता है, S3-compatible storage (Cloudflare R2 या Backblaze B2), और एक short share URL जहाँ decryption key # के बाद रहती है ताकि वह कभी server तक न पहुँचे। आप लगभग 400 lines of code में एक working version ship कर सकते हैं और इसे प्रति माह ₹400 से कम में host कर सकते हैं।

Architecture Decisions जो वास्तव में मायने रखते हैं

सबसे महत्वपूर्ण निर्णय यह है कि encryption key कहाँ रहती है। यदि यह कभी आपके server को touch करती है, तो आपके पास end-to-end encryption नहीं है, बल्कि extra steps के साथ server-side encryption है। सही pattern: browser में एक random 256-bit key generate करें, उससे फ़ाइल encrypt करें, ciphertext upload करें, और URL fragment में key डालें (https://yourapp.com/f/abc123#k=base64key)। Browsers HTTP requests में fragments कभी नहीं भेजते, इसलिए key client-side रहती है।

दूसरा बिंदु: chunked uploads। 100 MB से ऊपर की फ़ाइलों के लिए आपको resumable multipart uploads चाहिए, या कोई भी flaky Wi-Fi transfer को खत्म कर देता है। S3 का multipart API 5 MB minimum chunks और 10,000 parts तक support करता है, जो आपको 50 GB ceiling देता है। पहले दिन से इसके लिए plan करें।

Project Skeleton सेट करना

दो packages से शुरू करें: एक Vite + React frontend और एक Fastify backend। Frontend सभी crypto handle करता है, backend storage और metadata handle करता है। TypeScript उपयोग करें ताकि आपको ArrayBuffer और CryptoKey पर type safety मिले।

pnpm create vite@latest frontend -- --template react-ts
pnpm create fastify backend

Backend में ये deps जोड़ें: @fastify/multipart, @aws-sdk/client-s3, @aws-sdk/s3-request-presigner, और share metadata के लिए better-sqlite3। अपना SQLite schema tiny रखें: shares(id, object_key, size_bytes, expires_at, download_count, max_downloads)। कोई filenames नहीं, कोई user data नहीं, कोई IPs नहीं।

Frontend Encryption Pipeline लिखना

एक key generate करें, AES-256-GCM से encrypt करें, और URL fragment के लिए ciphertext blob और base64 key produce करें:

async function encryptFile(file: File) {
  const key = await crypto.subtle.generateKey(
    { name: 'AES-GCM', length: 256 }, true, ['encrypt', 'decrypt']
  );
  const iv = crypto.getRandomValues(new Uint8Array(12));
  const plaintext = await file.arrayBuffer();
  const ciphertext = await crypto.subtle.encrypt(
    { name: 'AES-GCM', iv }, key, plaintext
  );
  const rawKey = await crypto.subtle.exportKey('raw', key);
  const blob = new Blob([iv, new Uint8Array(ciphertext)]);
  return { blob, keyBase64: toBase64(rawKey) };
}

50 MB से ऊपर की फ़ाइलों के लिए, इसे एक streaming version से replace करें जो 4 MB chunks encrypt करता है और उन्हें एक ReadableStream में append करता है। Mobile Safari heap single ArrayBuffer में लगभग 400 MB से अधिक किसी भी चीज़ पर choke करता है।

Upload Endpoint डिज़ाइन करना

Backend को कुछ उपयोगी नहीं पता होना चाहिए। ciphertext के साथ POST accept करें, एक random 16-character URL-safe ID generate करें, expiry के साथ SQLite में store करें, और body को सीधे S3 में stream करें:

fastify.post('/upload', async (req, reply) => {
  const id = nanoid(16);
  const key = `blobs/${id}`;
  const upload = new Upload({
    client: s3,
    params: { Bucket: 'hexa-transfers', Key: key, Body: req.raw }
  });
  await upload.done();
  db.prepare('INSERT INTO shares VALUES (?, ?, ?, ?, 0, ?)').run(
    id, key, req.headers['content-length'], Date.now() + 7*86400*1000, 10
  );
  return { id };
});

Default expiry 7 दिन, max 10 downloads। आप aggressive defaults चाहते हैं क्योंकि विकल्प unbounded storage growth है। रात में expired blobs delete करने के लिए cron उपयोग करें।

Fragment Keys के साथ Share Links Generate करना

Upload finish होने के बाद, share URL client-side बनाएं:

const { id } = await uploadResponse.json();
const shareUrl = `${location.origin}/f/${id}#k=${keyBase64}`;

वह fragment user के browser को कभी नहीं छोड़ता। जब कोई recipient link click करता है, आपका React app window.location.hash पढ़ता है, key parse करता है, ciphertext fetch करता है, और locally decrypt करता है। Server के पास plaintext तक कोई रास्ता नहीं है सिवाय user को malicious JavaScript push करने के — जो कि ठीक वही कारण है जिसके लिए आपको tight Content Security Policy ship करनी चाहिए और subresource hashes pin करने चाहिए।

Download Flow Implement करना

Download page पर, ciphertext को stream के रूप में pull करें और chunk-aligned decrypt करें:

const keyRaw = base64ToBytes(location.hash.slice(3));
const key = await crypto.subtle.importKey(
  'raw', keyRaw, { name: 'AES-GCM' }, false, ['decrypt']
);
const resp = await fetch(`/blob/${id}`);
const iv = new Uint8Array(await resp.body.getReader().read().then(r => r.value.slice(0, 12)));
const ct = await resp.arrayBuffer();
const pt = await crypto.subtle.decrypt({ name: 'AES-GCM', iv }, key, ct.slice(12));
const url = URL.createObjectURL(new Blob([pt]));

बड़ी फ़ाइलों के लिए, StreamSaver.js या File System Access API उपयोग करें ताकि decrypted bytes RAM के बजाय सीधे disk पर पहुँचें।

पूरी चीज़ Deploy करना

Frontend: Cloudflare Pages या Vercel पर push करें, दोनों free tiers यह handle करते हैं। Backend: Caddy के पीछे Node 22 चलाने वाला एक single ₹400/माह का DigitalOcean droplet (automatic TLS 1.3)। Storage: Cloudflare R2 आपको zero egress fees देता है, जो scale पर file sharing के लिए killer feature है। WeTransfer, Smash, और SwissTransfer AWS egress पर fortune जलाते हैं; R2 economics को पूरी तरह बदल देता है।

Caddy के माध्यम से strict headers सेट करें: Strict-Transport-Security, Content-Security-Policy: default-src 'self'; script-src 'self', X-Content-Type-Options: nosniff, और Referrer-Policy: no-referrer। ये referrers या injected scripts के माध्यम से URL fragment leak करने के सामान्य vectors बंद करते हैं।

App को DPDP Act-Friendly बनाना

क्योंकि server केवल ciphertext देखता है, आपके पास DPDP Act 2023 की धारा 2 के तहत personal data के रूप में qualify होने वाला लगभग कुछ भी नहीं है। फिर भी, अपने processor relationships (R2 और DigitalOcean) document करें, 30-दिन max blob retention सेट करें, और एक स्पष्ट notice publish करें कि share links में keys हैं और उन्हें ऐसे channels पर transmit किया जाना चाहिए जिन पर sender को भरोसा है। Abuse को निरुत्साहित करने के लिए प्रति IP प्रति घंटे 50 uploads पर rate limiting जोड़ें बिना user identities log किए।

HexaTransfer मूलतः इसी architecture पर बनाया गया है — browser में Web Crypto, opaque blob storage, URL fragments में keys, servers पर zero plaintext। hexatransfer.com पर आज़माएं — मुफ़्त, कोई अकाउंट नहीं, अधिकतम 10 GB।

MVP काम करने के बाद क्या जोड़ें

एक बार basic flow ship हो जाए, सबसे high-value additions हैं: fragment key के ऊपर password protection (600,000 iterations के साथ PBKDF2), burner inbox के माध्यम से per-download email notifications, और abuse reporting जो ciphertext का hash flag करने देती है बिना content reveal किए। Accounts जोड़ने से बचें जब तक आपके पास specific reason न हो — वे रात भर में आपके app को एक privacy tool से data liability में बदल देते हैं। छोटा ship करें, opinionated रहें, और crypto को heavy lifting करने दें।

एंड-टू-एंड एन्क्रिप्शन के साथ बड़ी फ़ाइलें सुरक्षित रूप से भेजें

एंड-टू-एंड एन्क्रिप्शन के साथ 10 GB तक की फ़ाइलें मुफ़्त में ट्रांसफ़र करें। अकाउंट की आवश्यकता नहीं। अपलोड से पहले आपकी फ़ाइलें ब्राउज़र में एन्क्रिप्ट की जाती हैं — कोई और उन्हें पढ़ नहीं सकता।

फ़ाइल भेजें