सामग्री पर जाएँ
HexaTransfer
ब्लॉग पर वापस
एन्क्रिप्शन और सुरक्षा

एन्क्रिप्शन परफ़ॉर्मेंस ऑप्टिमाइज़ेशन: ब्राउज़र में फ़ास्ट क्रिप्टो

बड़े फ़ाइल ट्रांसफर के लिए ब्राउज़र एन्क्रिप्शन परफ़ॉर्मेंस ऑप्टिमाइज़ करें। स्ट्रीमिंग एन्क्रिप्शन, Web Workers और चंक प्रोसेसिंग।

ब्राउज़र में 5 GB फाइल एन्क्रिप्ट करना UI को freeze किए बिना मुमकिन है — इसके लिए कुछ खास तकनीकों की ज़रूरत है: hardware-accelerated AES-256-GCM के लिए Web Crypto API (AES-NI के साथ 1-2 GB/s), memory bound रखने के लिए 1-4 MB blocks में chunked processing, main thread responsive रखने के लिए Web Workers, FileReader.readAsArrayBuffer() की बजाय File.stream() से streaming reads, और careful nonce management ताकि chunks parallel में एन्क्रिप्ट हो सकें। Pure-JavaScript क्रिप्टो लाइब्रेरीज़ Web Crypto से 10-20x धीमी हैं और केवल उन primitives के लिए रखी जानी चाहिए जो browser natively expose नहीं करता। यहाँ real hardware पर multi-hundred megabyte-per-second throughput पाने का तरीका है।

पहले Baseline Measurements लें

ऑप्टिमाइज़ करने से पहले मापें। Chrome 120 पर 2024 MacBook Air M2 में, tight loop में AES-256-GCM से 1 GB buffer एन्क्रिप्ट करने पर ~1.7 GB/s मिलता है। वही operation mid-range Android phone (Pixel 7) पर ~600 MB/s। Software-only AES वाला 2015 Intel laptop ~250 MB/s।

यह बताता है: Web Crypto AES-GCM ज़्यादातर encrypted file transfer flows में bottleneck नहीं है। Bottleneck आमतौर पर file reading, ArrayBuffers के बीच JavaScript marshaling, या network upload है। पहले उन्हें optimize करें।

In-app benchmark:

const blob = new Uint8Array(1024 * 1024 * 100); // 100 MB
const key = await crypto.subtle.generateKey(
  { name: "AES-GCM", length: 256 }, true, ["encrypt"]
);
const iv = crypto.getRandomValues(new Uint8Array(12));
const start = performance.now();
await crypto.subtle.encrypt({ name: "AES-GCM", iv }, key, blob);
console.log(`${(100 / (performance.now() - start) * 1000).toFixed(0)} MB/s`);

Chrome, Firefox, Safari पर run करें। Apple Silicon पर Chrome सबसे तेज़; Firefox थोड़ा धीमा; Intel पर Safari उससे थोड़ा पीछे। Mobile desktop की ~30-50% speed पर चलता है।

Web Crypto उपयोग करें, JavaScript Libraries नहीं

AES-GCM, AES-CBC, PBKDF2, HMAC, RSA, ECDH, ECDSA, और SHA-256/384/512 के लिए browser का native Web Crypto API hardware acceleration उपयोग करता है — x86 पर AES-NI, mobile पर ARMv8 crypto extensions। @noble/ciphers या pure-JS crypto-js जैसी लाइब्रेरीज़ इन instructions तक नहीं पहुँच सकतीं।

1 MB inputs पर AES-256-GCM की typical speed ratio:

  • Web Crypto (hardware accel): 1-2 GB/s
  • libsodium.js WASM: 400-800 MB/s
  • @noble/ciphers pure JS: 100-200 MB/s
  • crypto-js pure JS: 30-80 MB/s

5 GB फाइल पर Web Crypto और pure JS का फ़र्क ~3 seconds बनाम ~50 seconds है। User-visible अंतर। Web Crypto को हमेशा prefer करें जहाँ यह support करता हो। WASM libraries (libsodium.js, argon2-browser) केवल उन algorithms के लिए उपयोग करें जो Web Crypto में नहीं हैं (ChaCha20-Poly1305, Argon2id, older browsers पर X25519)।

Large Files के लिए Chunk Processing

~500 MB से बड़ी फाइलें ज़्यादातर devices पर एक single ArrayBuffer में आरामदायक नहीं समाती। उन्हें 1-4 MB pieces में chunk करें और हर एक को encrypt करें।

const CHUNK_SIZE = 4 * 1024 * 1024; // 4 MB

async function encryptLargeFile(file, key) {
  const chunks = [];
  let chunkIndex = 0;
  for (let offset = 0; offset < file.size; offset += CHUNK_SIZE) {
    const chunk = await file.slice(offset, offset + CHUNK_SIZE).arrayBuffer();
    const iv = new Uint8Array(12);
    new DataView(iv.buffer).setBigUint64(4, BigInt(chunkIndex++));
    const ct = await crypto.subtle.encrypt(
      { name: "AES-GCM", iv }, key, chunk
    );
    chunks.push({ iv, ct: new Uint8Array(ct) });
  }
  return chunks;
}

4 MB chunks क्यों? छोटे chunks (जैसे 64 KB) Web Crypto API के per-call overhead से dominated होते हैं। बड़े chunks (जैसे 64 MB) L2/L3 cache में fit नहीं होते और memory pressure बढ़ाते हैं। Desktop और mobile दोनों पर 1-4 MB sweet spot होता है।

UI Responsive रखने के लिए Web Workers

Main thread पर एन्क्रिप्शन rendering और input block करता है। ~500 ms से ज़्यादा काम के लिए Web Worker में offload करें।

// worker.js
self.onmessage = async (e) => {
  const { chunk, key, iv } = e.data;
  const ciphertext = await crypto.subtle.encrypt(
    { name: "AES-GCM", iv }, key, chunk
  );
  self.postMessage(ciphertext, [ciphertext]);
};

// main thread
const worker = new Worker('/worker.js');
worker.postMessage({ chunk, key, iv }, [chunk]);
worker.onmessage = (e) => { /* handle ct */ };

ArrayBuffers को postMessage के दूसरे argument से transfer करें — यह ownership move करता है (zero-copy)। बिना transfer के, 4 MB chunk clone करने में ~20 ms overhead आता है per chunk।

Web Crypto API Workers में available है, इसलिए actual एन्क्रिप्शन वहाँ main thread जैसी identical performance से चलती है।

Parallel Chunk Encryption

Per-chunk AES-GCM encryption independent है जब तक nonces collide न करें। Chunk index से deterministically nonces derive करें और multiple Workers में parallel encrypt करें। ~4 workers के बाद diminishing returns आते हैं क्योंकि Web Crypto इतना fast है कि bottleneck file reading और inter-thread message passing में shift हो जाता है। Complexity commit करने से पहले benchmark करें; कभी-कभी single-worker sequential encryption overhead की वजह से multi-worker parallel जितनी ही fast होती है।

Readable Streams से Streaming

सच में huge files (20+ GB) के लिए, एक साथ chunks भी memory में न लोड करें। File.stream() उपयोग करें:

const reader = file.stream().getReader();
const writer = uploadStream.getWriter();
let chunkIndex = 0;

while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  const iv = new Uint8Array(12);
  new DataView(iv.buffer).setBigUint64(4, BigInt(chunkIndex++));
  const ct = await crypto.subtle.encrypt(
    { name: "AES-GCM", iv }, key, value
  );
  await writer.write(new Uint8Array(ct));
}
await writer.close();

Memory use एक chunk तक bounded रहता है। File size चाहे जो हो, memory usage 10 MB के नीचे रहती है।

Upload Concurrency

एन्क्रिप्शन upload के parallel में चलता है, serially नहीं। जब chunk N upload हो, chunk N+1 एन्क्रिप्ट हो रहा हो। Pipeline बनाएं:

const MAX_IN_FLIGHT = 4;

async function pipeline() {
  // पहले chunks का encryption शुरू करें
  for (let i = 0; i < MAX_IN_FLIGHT; i++) startEncrypt(i);
  // जैसे-जैसे complete हों, upload शुरू करें और next encryption enqueue करें
}

TCP slow-start और TLS handshake overhead से initial uploads slow होते हैं। Single origin पर 4-8 concurrent uploads रखने से pipe full रहती है बिना browser limits trip किए (Chrome/Firefox में 6 connections per origin)।

Missing Primitives के लिए WebAssembly

Argon2id key derivation या ChaCha20-Poly1305 के लिए Web Crypto में native support नहीं है। WASM libraries gap fill करती हैं:

  • libsodium.js: Argon2id, XChaCha20-Poly1305, crypto_secretstream देता है
  • argon2-browser: केवल Argon2 लेकिन smaller bundle
  • @noble/hashes: pure-JS Argon2 (धीमा) tiny bundle के साथ

WASM versions ज़्यादातर crypto workloads के लिए native speed का 60-80% achieve करते हैं। Upload और download पर 1-2 second Argon2id derivation acceptable है; 5 second pure-JS नहीं।

WASM dynamically load करें ताकि initial page render block न हो:

const sodium = await import('libsodium-wrappers');
await sodium.ready;

Progress Reporting

Large encryptions को progress feedback चाहिए वरना users मानते हैं app freeze हो गई। Encrypted bytes count करें और progress events post करें:

let processed = 0;
for await (const chunk of chunks) {
  await encryptChunk(chunk);
  processed += chunk.size;
  onProgress({ done: processed, total: file.size, pct: processed / file.size });
}

UI updates को requestAnimationFrame या timestamp check से ~10 Hz पर throttle करें — ज़्यादा frequent updates repaints पर cycles waste करते हैं।

Memory Ceiling और GC Pressure

हर ArrayBuffer तब तक जीता है जब तक referenced है। 20 encrypted chunks of 4 MB रखना ~80 MB memory pin करता है। iOS Safari जैसे tight memory limits वाले mobile browsers पर (per-tab ~200-400 MB cap) यह matter करता है।

References promptly release करें:

for (let i = 0; i < chunks.length; i++) {
  const chunk = chunks[i];
  chunks[i] = null; // GC को reclaim करने दें
  const ct = await encrypt(chunk);
  await upload(ct);
}

Memory में encrypted chunks का full array न रखें; uploader को stream करें और references drop करते जाएं।

Real-World Targets

Browser tab में 1 GB encrypted file transfer के लिए: encryption time 1-3 seconds (hardware accelerated), 300 Mbps connection पर upload time 30 seconds, total ~35 seconds wall clock (mostly network-bound), proper streaming के साथ peak memory 50 MB से कम, UI हर समय responsive (main thread कभी 50 ms से ज़्यादा block नहीं)। इन targets miss करने पर users notice करते हैं। HexaTransfer का 10 GB cap browser में achievable है क्योंकि Web Crypto और chunked streaming पूरे path को efficient रखते हैं।

hexatransfer.com पर आज़माएं — मुफ्त, बिना अकाउंट, 10 GB तक।

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

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

फ़ाइल भेजें