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

AES-GCM इम्प्लीमेंटेशन गाइड: ऑथेंटिकेटेड एन्क्रिप्शन सही तरीके से

अपने वेब ऐप में AES-GCM एन्क्रिप्शन सही से इम्प्लीमेंट करें। नॉन्स मैनेजमेंट, की हैंडलिंग और आम गलतियां जो बचनी चाहिए।

AES-GCM (Galois/Counter Mode) AES-CTR encryption को GHASH authentication के साथ combine करके Authenticated Encryption with Associated Data (AEAD) बनाता है। सही implementation में चाहिए: 256-bit key, एक 96-bit (12-byte) nonce जो प्रति key unique हो (कभी reuse न हो), 128-bit authentication tag, और optionally Associated Data (AAD) जो verify होती है पर encrypt नहीं। NIST SP 800-38D इस exact construction को specify करता है। इसमें कोई भी गलती — विशेषकर nonce reuse — GCM की security को बर्बाद कर देती है: एक बार भी (key, nonce) pair repeat होने पर attacker authentication key recover कर सकता है और मनमाना ciphertext forge कर सकता है। यह guide AES-GCM को browser, Node.js और server contexts में सही तरीके से use करने का तरीका बताती है।

GCM वास्तव में क्या guarantee देता है

दो properties:

Confidentiality: key के बिना plaintext recover नहीं होता। AES-GCM की CTR-mode encryption layer यह provide करती है।

Integrity और Authenticity: ciphertext, nonce या associated data में किसी भी बदलाव से decryption fail होता है। GHASH एक 128-bit tag produce करता है जो decrypt पर constant-time verify होता है।

GCM क्या guarantee नहीं देता: non-repudiation (यह symmetric है, इसलिए key रखने वाला कोई भी valid ciphertext बना सकता है), replay protection (यह higher-layer concern है), या ordering (streams के लिए chaining चाहिए)।

मुख्य बात: GCM तभी secure रहता है जब nonces प्रति key unique हों। ज़्यादातर unique नहीं, आमतौर पर unique नहीं — वास्तव में unique। Security proof reuse पर collapse हो जाता है।

Nonce Management: सबसे ज़रूरी बात

96-bit nonce दो तरीकों से generate हो सकता है:

Random: crypto.getRandomValues(new Uint8Array(12))। एक key के under random 96-bit nonces के साथ, birthday-bound collisions लगभग 2^48 encryptions पर आती हैं। NIST safety margin suggest करता है, इसलिए प्रति key 2^32 तक सीमित रखें।

Counter: एक 96-bit integer increment करें। 2^96 messages तक uniqueness guarantee। Monotonic state चाहिए — distributed systems में मुश्किल।

प्रति फ़ाइल fresh key के साथ फ़ाइल ट्रांसफर के लिए, random nonces पूरी तरह safe हैं। एक single file key के under chunked encryption के लिए counter use करें जहाँ nonce chunk index encode करता है:

const nonce = new Uint8Array(12);
new DataView(nonce.buffer).setUint32(0, messageId);
new DataView(nonce.buffer).setBigUint64(4, BigInt(chunkIndex));

खतरनाक case: multiple processes एक shared key के under random nonces से millions/second की scale पर encrypt कर रहे हों। Birthday collisions probable हो जाती हैं। अगर processes में keys share करनी हों, तो process ID prefix के साथ coordinated counter use करें।

64-bit Nonces न उपयोग करें

AES-GCM variable nonce lengths support करता है, लेकिन केवल 96-bit nonces NIST 800-38D में specify किया optimized construction use करते हैं। अन्य lengths (64 या 128 bits) एक GHASH pre-processing step trigger करती हैं जो performance कम करती है। Web Crypto API non-96-bit IVs accept करता है लेकिन spec 96 recommend करता है। बस 96 use करें।

Tag Length: इसे छोटा न करें

GCM का tag 128 bits तक होता है। कुछ specs 96, 64 या 32 bits तक truncation allow करते हैं। यह न करें। Truncated tags forgery attacks को आसान बनाते हैं, और बचत (4-12 bytes per message) फ़ाइल ट्रांसफर के लिए irrelevant है। Web Crypto का AES-GCM, tagLength parameter (default 128) के ज़रिए 128-bit tags default करता है। इसे न बदलें।

Associated Data (AAD)

AAD वह data है जो authenticated है लेकिन encrypted नहीं। इसे उस metadata के लिए use करें जो ciphertext से bound हो: filename, content type, expiration timestamp, uploader ID।

await crypto.subtle.encrypt(
  {
    name: "AES-GCM",
    iv: nonce,
    additionalData: new TextEncoder().encode(JSON.stringify({
      filename: "report.pdf",
      contentType: "application/pdf",
      expires: 1712345678,
    })),
  },
  key,
  plaintext
);

अगर attacker AAD modify करे, तो decryption fail होगा। यह swap attacks रोकता है। Receiver को decrypt करने के लिए exact AAD पता होना चाहिए, इसलिए इसे ciphertext के साथ store करें।

Key Generation और Derivation

Per-file keys के लिए:

const key = await crypto.subtle.generateKey(
  { name: "AES-GCM", length: 256 },
  true,
  ["encrypt", "decrypt"]
);

2026 में 256 bits default है। 128-bit AES अभी भी secure है लेकिन post-quantum margin कम है।

Password-derived keys के लिए:

const aesKey = await crypto.subtle.deriveKey(
  {
    name: "PBKDF2",
    salt: crypto.getRandomValues(new Uint8Array(16)),
    iterations: 600000,
    hash: "SHA-256",
  },
  passwordKey,
  { name: "AES-GCM", length: 256 },
  false,
  ["encrypt", "decrypt"]
);

Salt को ciphertext के साथ store करें। यह secret नहीं है; बस प्रति password unique होना चाहिए।

Critical Code Path

एक minimal encrypt function:

async function encrypt(key, plaintext, aad = new Uint8Array()) {
  const nonce = crypto.getRandomValues(new Uint8Array(12));
  const ciphertext = new Uint8Array(
    await crypto.subtle.encrypt(
      { name: "AES-GCM", iv: nonce, additionalData: aad },
      key,
      plaintext
    )
  );
  return { nonce, ciphertext, aad };
}

Proper error handling के साथ decrypt:

async function decrypt(key, { nonce, ciphertext, aad }) {
  try {
    return await crypto.subtle.decrypt(
      { name: "AES-GCM", iv: nonce, additionalData: aad },
      key,
      ciphertext
    );
  } catch (e) {
    throw new Error("Decryption failed: ciphertext tampered or wrong key");
  }
}

decrypt call, tag mismatch, short ciphertext या wrong key पर OperationError throw करता है। किसी भी exception को integrity failure मानें।

बड़ी फ़ाइलों को Chunks में Encrypt करना

कुछ सौ megabytes से बड़ी फ़ाइलों के लिए, memory pressure से बचने के लिए chunks में encrypt करें:

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

Caveat: chunked AES-GCM truncation detect नहीं करता। बचाव के लिए हर chunk के AAD में total chunk count include करें, या libsodium का crypto_secretstream use करें।

Server-Side Decrypt (Node.js)

Node का crypto module browser में encrypt data decrypt कर सकता है:

const { createDecipheriv } = require('crypto');

function decrypt(key, nonce, ciphertextWithTag) {
  const tag = ciphertextWithTag.slice(-16);
  const ct = ciphertextWithTag.slice(0, -16);
  const decipher = createDecipheriv('aes-256-gcm', key, nonce);
  decipher.setAuthTag(tag);
  return Buffer.concat([decipher.update(ct), decipher.final()]);
}

Web Crypto 128-bit tag को ciphertext के साथ append करता है; Node का API tag और ciphertext अलग-अलग expect करता है।

Performance Numbers

Typical 2024-2026 hardware पर AES-NI के साथ:

  • Native (OpenSSL, AES-NI): 3-5 GB/s per core
  • Web Crypto (browser with hardware accel): 1-2 GB/s
  • libsodium.js WASM AES-GCM: 400-800 MB/s
  • Pure JS (@noble/ciphers): 50-150 MB/s

1 GB फ़ाइल के लिए, Web Crypto encryption 0.5-1 second में चलता है। Pure JS 7-20 seconds लेता है। Large file transfer UX के लिए, Web Crypto practical choice है।

आम गलतियाँ

  • Nonce reuse: catastrophic। सबसे बड़ा failure mode।
  • crypto.getRandomValues() की जगह Math.random() use करना।
  • AAD से associated metadata authenticate करना भूलना।
  • CBC mode use करना जबकि GCM integrity automatically handle करता है।
  • Decrypt errors silently catch करना और garbage return करना। हमेशा loud fail करें।
  • अपना खुद का GCM roll करना। Web Crypto, libsodium, या node:crypto use करें।

HexaTransfer 96-bit random nonces, 128-bit tags के साथ Web Crypto का AES-256-GCM use करता है — simple, correct और fast।

कब कुछ और चुनें

AES-GCM फ़ाइल ट्रांसफर के लिए optimal है, लेकिन specific cases में:

  • XChaCha20-Poly1305: 192-bit nonces random-nonce safety को किसी भी scale पर trivial बनाते हैं। libsodium इसे provide करता है।
  • AES-GCM-SIV: misuse-resistant; nonce reuse से key leak नहीं होती। जहाँ nonce uniqueness guarantee न हो वहाँ useful।

Standard web stack में most file transfer workloads के लिए, fresh key per file और random 96-bit nonces के साथ AES-256-GCM सही और सबसे आसानी से correctly implement होने वाला choice है।

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

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

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

फ़ाइल भेजें