← ब्लॉग पर वापस जाएँ

RedaktPDF आपकी PDF को कैसे एन्क्रिप्ट करता है: हमारे E2EE आर्किटेक्चर पर एक विस्तृत नज़र

Jury D'Ambros··8 मिनट का पठन

अधिकांश ऑनलाइन PDF एडिटर आपकी फ़ाइलों को अपने सर्वर पर प्रोसेस करते हैं। वे आपके डॉक्यूमेंट को प्लेनटेक्स्ट में प्राप्त करते हैं, उसमें हेरफेर करते हैं, और वापस भेज देते हैं। जिस क्षण आपकी फ़ाइल आपके ब्राउज़र से बाहर निकलती है, वह उस कंपनी के इंफ्रास्ट्रक्चर के लिए पठनीय हो जाती है — उनके इंजीनियर, उनके लॉग, और कोई भी जो उनके सिस्टम में अनधिकृत पहुँच पा लेता है।

RedaktPDF अलग तरह से काम करता है। एक रजिस्टर्ड यूज़र के रूप में आप जो भी PDF अपलोड करते हैं, वह आपके ब्राउज़र में एन्क्रिप्ट हो जाती है, इससे पहले कि एक भी बाइट हमारे सर्वर तक पहुँचे। सर्वर ऐसा सिफरटेक्स्ट स्टोर करता है जिसे वह पढ़ नहीं सकता। यह पोस्ट विस्तार से समझाती है कि यह कैसे काम करता है — की हायरार्की, क्रिप्टोग्राफ़िक प्रिमिटिव्स, और हर विकल्प के पीछे के डिज़ाइन निर्णय।

ग़ैर-तकनीकी अवलोकन के लिए देखें PDF एडिटिंग के लिए एंड-टू-एंड एन्क्रिप्शन क्यों ज़रूरी है

ज़ीरो-नॉलेज मॉडल

क्रिप्टोग्राफ़ी में "zero-knowledge" शब्द का कई तरीकों से प्रयोग होता है, लेकिन इस संदर्भ में इसका विशिष्ट अर्थ है: सर्वर ऐसा डेटा रखता है जो उस जानकारी के बिना क्रिप्टोग्राफ़िक रूप से बेकार है जो केवल यूज़र के पास होती है।

यहाँ बताया गया है कि RedaktPDF का सर्वर आपकी एन्क्रिप्टेड डॉक्यूमेंट्स के बारे में क्या जानता है:

  • रैप किया हुआ (एन्क्रिप्टेड) KEK — आपकी मास्टर की के बिना बेकार
  • रैप की हुई (एन्क्रिप्टेड) फ़ाइल कीज़ — KEK के बिना बेकार
  • S3 में एन्क्रिप्टेड ब्लॉब — फ़ाइल कीज़ के बिना अपठनीय
  • PBKDF2 सॉल्ट — गोपनीय नहीं; की डेरिवेशन के लिए आवश्यक
  • आपका ईमेल पता और अकाउंट मेटाडेटा

यहाँ बताया गया है कि सर्वर क्या कभी नहीं देखता:

  • आपका पासवर्ड (केवल ऑथेंटिकेशन के लिए एक bcrypt हैश स्टोर होता है)
  • मास्टर की — आपके ब्राउज़र में डिराइव होती है, कभी ट्रांसमिट नहीं की जाती
  • प्लेनटेक्स्ट में KEK — केवल आपके ब्राउज़र में अनरैप होती है
  • प्लेनटेक्स्ट में फ़ाइल कीज़ — केवल आपके ब्राउज़र में अनरैप होती हैं
  • PDF कंटेंट, पेज इमेज, और एक्सट्रैक्ट किया हुआ टेक्स्ट — अपलोड से पहले एन्क्रिप्ट किए जाते हैं

व्यावहारिक रूप से यह क्यों मायने रखता है? सबसे ख़राब स्थिति की कल्पना करें: एक हमलावर पूरा डेटाबेस और हर S3 ऑब्जेक्ट चुरा लेता है। उसके पास रैप की गई कीज़ और एन्क्रिप्टेड ब्लॉब हैं। आपके पासवर्ड के बिना, वह मास्टर की डिराइव नहीं कर सकता। मास्टर की के बिना, रैप किया हुआ KEK डिक्रिप्ट नहीं हो सकता। KEK के बिना, प्रति-फ़ाइल कीज़ सीलबंद रहती हैं। ब्रीच से कुछ भी उपयोगी हाथ नहीं लगता।

यह कोई संविदात्मक प्रतिबद्धता नहीं है — यह आर्किटेक्चर की एक क्रिप्टोग्राफ़िक संपत्ति है।

Key हायरार्की

RedaktPDF तीन-स्तरीय key हायरार्की का उपयोग करता है। हर स्तर का एक अलग उद्देश्य है।

User Password
    |
    v PBKDF2(password, salt, 600,000 iterations, SHA-256)
Master Key (MK) ---- stored nowhere (derived on-demand)
    |
    v AES-GCM wrapKey
Key Encryption Key (KEK) ---- wrapped copy stored in DB
    |
    v AES-GCM wrapKey (per document)
File Key (FK) ---- wrapped copy stored in DB per document
    |
    v AES-256-GCM encrypt
Encrypted PDF, page images, text metadata ---- stored in S3

Master Key (MK): PBKDF2 का उपयोग करके आपके पासवर्ड से डिराइव की जाती है। यह कहीं भी स्टोर नहीं होती — न सर्वर पर, न मौजूदा सेशन से आगे ब्राउज़र में। हर बार जब आप एन्क्रिप्टेड सेशन में लॉग इन करते हैं, MK आपके पासवर्ड से फिर से डिराइव होती है और केवल मेमोरी में मौजूद रहती है। अगर आप टैब बंद कर देते हैं, तो वह ख़त्म।

Key Encryption Key (KEK): एक यादृच्छिक रूप से जनरेट की गई 256-बिट AES-GCM की। यह एक बार जनरेट होती है जब आप एन्क्रिप्शन इनेबल करते हैं और फिर तुरंत MK से रैप (एन्क्रिप्ट) हो जाती है। रैप किया हुआ रूप डेटाबेस में स्टोर होता है। प्लेनटेक्स्ट रूप केवल सक्रिय सेशन के दौरान ब्राउज़र मेमोरी में मौजूद रहता है।

KEK एक संचालन संबंधी कारण से मौजूद है: पासवर्ड बदलना। जब आप अपना पासवर्ड बदलते हैं, तो एक नया MK डिराइव होता है। KEK परत के बिना, हर एक डॉक्यूमेंट की फ़ाइल की को नए MK से फिर से एन्क्रिप्ट करना पड़ता। KEK परत के साथ, केवल KEK रैपर को अपडेट करने की ज़रूरत होती है — चाहे आपके पास कितनी भी डॉक्यूमेंट हों, सिर्फ़ एक डेटाबेस राइट। सभी मौजूदा फ़ाइल कीज़ वैध बनी रहती हैं।

File Key (FK): एक यादृच्छिक रूप से जनरेट की गई 256-बिट AES-GCM की, हर डॉक्यूमेंट के लिए अद्वितीय। यह वास्तविक PDF बाइट्स, पेज इमेज, थंबनेल, और एक्सट्रैक्ट किए गए टेक्स्ट को एन्क्रिप्ट करती है। रैप किया हुआ रूप डॉक्यूमेंट मेटाडेटा के साथ डेटाबेस में स्टोर होता है। प्रति डॉक्यूमेंट कीज़ को अलग रखने का मतलब है कि की के काल्पनिक समझौते से केवल एक डॉक्यूमेंट प्रभावित होगा, आपकी पूरी फ़ाइल लाइब्रेरी नहीं।

Key डेरिवेशन: पासवर्ड से मास्टर key तक

मास्टर key डेरिवेशन Web Crypto API के PBKDF2 कार्यान्वयन का उपयोग करती है। यहाँ packages/crypto/src/index.ts से प्रोडक्शन कोड है:

const PBKDF2_ITERATIONS = 600_000;

export async function deriveMasterKey(
  password: string,
  salt: Uint8Array,
): Promise<CryptoKey> {
  const keyMaterial = await globalThis.crypto.subtle.importKey(
    'raw',
    new TextEncoder().encode(password),
    'PBKDF2',
    false,
    ['deriveKey'],
  );

  return globalThis.crypto.subtle.deriveKey(
    {
      name: 'PBKDF2',
      salt: salt as unknown as ArrayBuffer,
      iterations: PBKDF2_ITERATIONS,
      hash: 'SHA-256',
    },
    keyMaterial,
    { name: 'AES-GCM', length: 256 },
    false, // not extractable
    ['encrypt', 'decrypt', 'wrapKey', 'unwrapKey'],
  );
}

कोड को क्रम से समझें:

  1. importKey('raw', ...) — UTF-8 एन्कोडेड पासवर्ड को रॉ की मटीरियल के रूप में इम्पोर्ट करता है। यह अभी एक उपयोगी की नहीं है; यह केवल बाइट्स हैं जो डेरिवेशन फ़ंक्शन में फ़ीड होती हैं।

  2. deriveKey(...) — मास्टर की उत्पन्न करने के लिए SHA-256 और 600,000 इटरेशन के साथ PBKDF2 लागू करता है।

  3. { name: 'AES-GCM', length: 256 } — निर्दिष्ट करता है कि आउटपुट 256-बिट AES-GCM की है।

  4. false (extractable) — यह महत्वपूर्ण है। मास्टर की नॉन-एक्सट्रैक्टेबल है। एक ही ब्राउज़र कॉन्टेक्स्ट में चलने वाला JavaScript कोड भी रॉ की बाइट्स पढ़ नहीं सकता। यह Web Crypto API के आंतरिक की स्टोर के अंदर मौजूद रहती है और केवल क्रिप्टोग्राफ़िक ऑपरेशन्स के लिए उपयोग की जा सकती है, कभी एक्सपोर्ट नहीं की जा सकती। यह किसी दुर्भावनापूर्ण स्क्रिप्ट को मेमोरी से की पढ़ने से रोकता है।

  5. ['encrypt', 'decrypt', 'wrapKey', 'unwrapKey'] — की के उपयोग। मास्टर की KEK को रैप और अनरैप कर सकती है, और ज़रूरत पड़ने पर सीधे एन्क्रिप्ट/डिक्रिप्ट भी कर सकती है।

600,000 इटरेशन क्यों? PBKDF2 जान-बूझकर धीमा होता है — हर अतिरिक्त इटरेशन ब्रूट-फ़ोर्स अटैक को आनुपातिक रूप से अधिक महंगा बनाता है। 2023 तक OWASP की अनुशंसा PBKDF2-SHA256 के लिए 600,000 इटरेशन है। यह एक पासवर्ड अनुमान को मापने योग्य CPU समय लेने पर मजबूर करता है। 600,000 इटरेशन पर, चुराए गए सॉल्ट के विरुद्ध डिक्शनरी अटैक की कोशिश करने वाले हमलावर को हर उम्मीदवार पासवर्ड के लिए वह CPU लागत चुकानी पड़ती है। यहाँ तक कि GPU क्लस्टर के साथ भी, एक मज़बूत पासवर्ड को क्रैक करना अव्यावहारिक है।

16-बाइट का यादृच्छिक सॉल्ट यह सुनिश्चित करता है कि समान पासवर्ड अलग-अलग मास्टर कीज़ उत्पन्न करें, जिससे रेनबो टेबल अटैक विफल हो जाते हैं।

PDF को एन्क्रिप्ट करना

जब फ़ाइल की उपलब्ध हो जाती है, तो सारा डेटा एन्क्रिप्शन एक ही फ़ंक्शन का उपयोग करता है। यहाँ क्रिप्टो पैकेज से प्रोडक्शन का encryptBlob है:

export async function encryptBlob(
  data: Uint8Array,
  key: CryptoKey,
): Promise<Uint8Array> {
  const iv = globalThis.crypto.getRandomValues(new Uint8Array(IV_BYTES));
  const ciphertext = await globalThis.crypto.subtle.encrypt(
    { name: 'AES-GCM', iv },
    key,
    data as unknown as ArrayBuffer,
  );
  return concat(iv, new Uint8Array(ciphertext));
}

तीन बातें ध्यान देने योग्य हैं:

प्रति एन्क्रिप्शन यादृच्छिक IV। IV_BYTES 12 (बाइट्स) है, जो AES-GCM के लिए NIST-अनुशंसित IV लंबाई है। encryptBlob के हर कॉल के लिए एक नया 12-बाइट IV जनरेट होता है। इसका मतलब है कि एक ही PDF को दो बार एन्क्रिप्ट करने से अलग-अलग सिफरटेक्स्ट उत्पन्न होते हैं। अगर एक ही की के साथ IV का पुनः उपयोग किया जाए, तो AES-GCM की सुरक्षा ध्वस्त हो जाएगी — एक ही की और IV के तहत दो सिफरटेक्स्ट प्लेनटेक्स्ट का XOR लीक करते हैं और हमलावर को ऑथेंटिकेशन टैग जाली बनाने की अनुमति देते हैं। यादृच्छिक IV इस ख़तरे को समाप्त कर देते हैं।

ऑथेंटिकेटेड एन्क्रिप्शन। AES-GCM एक AEAD (Authenticated Encryption with Associated Data) सिफर है। यह गोपनीयता (कंटेंट पढ़ा नहीं जा सकता) और अखंडता (कंटेंट को चुपचाप बदला नहीं जा सकता) दोनों प्रदान करता है। सिफरटेक्स्ट के साथ जुड़ा GCM ऑथेंटिकेशन टैग किसी भी छेड़छाड़ का पता लगाता है। अगर S3 में स्टोर किया गया एन्क्रिप्टेड ब्लॉब बदला जाता है, तो डिक्रिप्शन भ्रष्ट प्लेनटेक्स्ट लौटाने के बजाय एरर थ्रो करेगा।

सेल्फ़-डिस्क्राइबिंग फॉर्मेट। IV को सिफरटेक्स्ट के आगे जोड़ा जाता है (concat(iv, new Uint8Array(ciphertext)))। आउटपुट एक सिंगल बाइट ऐरे है: [12 bytes IV][remaining bytes: ciphertext + 16-byte auth tag]। डिक्रिप्शन पहले 12 बाइट्स को IV के रूप में पढ़ता है, बाकी को ऑथेंटिकेटेड सिफरटेक्स्ट के रूप में। अलग IV स्टोरेज की ज़रूरत नहीं है।

यही फ़ंक्शन PDF फ़ाइल बाइट्स, हर रेंडर की गई पेज इमेज, थंबनेल इमेज, और एक्सट्रैक्ट किए गए टेक्स्ट JSON को एन्क्रिप्ट करता है — हर वह चीज़ जो डॉक्यूमेंट कंटेंट को उजागर कर सकती है।

जब आप एडिट लागू करने के लिए secure PDF editor का उपयोग करते हैं, तो वे ऑपरेशन्स पूरी तरह आपके ब्राउज़र में असेंबल और एक्सपोर्ट होते हैं। एडिटेड डॉक्यूमेंट कभी डिक्रिप्ट रूप में फिर से अपलोड नहीं किया जाता।

अपलोड फ्लो

एन्क्रिप्टेड PDF अपलोड करने का क्रम यहाँ है:

  1. आपका ब्राउज़र PDF फ़ाइल को Uint8Array के रूप में पढ़ता है।
  2. PDF.js हर पेज को स्थानीय रूप से 150 DPI (फ़ुल रिज़ॉल्यूशन) और 72 DPI (थंबनेल) पर रेंडर करता है। कोई भी रेंडरिंग सर्वर-साइड पर नहीं होती।
  3. PDF.js सर्च और सिलेक्शन सपोर्ट के लिए टेक्स्ट पोज़िशन स्थानीय रूप से एक्सट्रैक्ट करता है।
  4. ब्राउज़र एक नई यादृच्छिक फ़ाइल की (FK) जनरेट करता है।
  5. FK एन्क्रिप्ट करती है: PDF बाइट्स, हर रेंडर की गई पेज PNG, हर थंबनेल PNG, और टेक्स्ट पोज़िशन JSON — सब encryptBlob के माध्यम से।
  6. AES-GCM wrapKey का उपयोग करके FK को यूज़र के KEK से रैप किया जाता है।
  7. ब्राउज़र प्रीसाइन्ड URL के माध्यम से सीधे S3 पर एन्क्रिप्टेड PDF अपलोड करता है — सर्वर URL जारी करता है लेकिन कभी फ़ाइल कंटेंट प्राप्त नहीं करता।
  8. ब्राउज़र एन्क्रिप्टेड पेज ब्लॉब और रैप की गई FK को /api/documents/confirm-encrypted पर भेजता है।
  9. सर्वर एन्क्रिप्टेड ब्लॉब को S3 में और रैप की गई FK को डेटाबेस में स्टोर करता है। किसी भी बिंदु पर वह प्लेनटेक्स्ट PDF, पेज इमेज, या फ़ाइल की नहीं देखता।

यहाँ तक कि रिडैक्शन ऑपरेशन भी इस मॉडल का पालन करते हैं: डॉक्यूमेंट को एन्क्रिप्ट और अपलोड किए जाने से पहले रिडैक्शन ब्राउज़र में मौजूद PDF प्रतिनिधित्व पर क्लाइंट-साइड लागू किए जाते हैं।

की रैपिंग के लिए AES-GCM क्यों

की रैपिंग कार्यान्वयन पर एक नोट जो docs/SECURITY.md के डॉक्यूमेंटेशन तालिका से भिन्न है।

SECURITY.md तालिका की रैपिंग प्रिमिटिव के लिए "AES-KW (Key Wrap)" सूचीबद्ध करती है — RFC 3394 AES Key Wrap का संदर्भ। वास्तविक कार्यान्वयन AES-GCM के साथ wrapKey का उपयोग करता है। यहाँ wrapKek फ़ंक्शन है:

export async function wrapKek(
  kek: CryptoKey,
  masterKey: CryptoKey,
): Promise<string> {
  const iv = globalThis.crypto.getRandomValues(new Uint8Array(IV_BYTES));
  const wrapped = await globalThis.crypto.subtle.wrapKey(
    'raw',
    kek,
    masterKey,
    {
      name: 'AES-GCM',
      iv,
    },
  );
  return toBase64(concat(iv, new Uint8Array(wrapped)));
}

अंतर मायने रखता है: AES-KW (RFC 3394) IV का उपयोग नहीं करता। यह एक अंतर्निहित अखंडता जाँच मान के माध्यम से अखंडता प्रदान करता है, लेकिन इसका ऑथेंटिकेशन तंत्र GCM की तुलना में संकुचित है। यादृच्छिक IV के साथ AES-GCM पूर्ण AEAD प्रदान करता है — 128-बिट ऑथेंटिकेशन टैग के साथ गोपनीयता, अखंडता, और ऑथेंटिकेशन। रैप की गई की में किसी भी बदलाव का पता लगाया जा सकता है।

पूरे स्टैक में AES-GCM का उपयोग (डेटा एन्क्रिप्शन और की रैपिंग दोनों के लिए) का एक और व्यावहारिक लाभ है: स्थिरता। कार्यान्वयन एक ही प्रिमिटिव का उपयोग करता है जिसके गुण अच्छी तरह से समझे जाते हैं और जिसका ब्राउज़र सपोर्ट उत्कृष्ट है। दो अलग-अलग क्रिप्टोग्राफ़िक मोड के बारे में सोचने का संज्ञानात्मक बोझ नहीं है।

SECURITY.md तालिका एक डॉक्यूमेंटेशन गैप है; वास्तविक कार्यान्वयन अधिक मज़बूत है। यह पोस्ट दस्तावेज़ करती है कि कोड वास्तव में क्या करता है।

व्यवहार में इसका क्या मतलब है

इसे एक ठोस परिदृश्य के साथ जोड़ें। मान लीजिए कि RedaktPDF के डेटाबेस और सभी S3 ऑब्जेक्ट कल चुरा लिए गए। हमलावर को मिलता है:

  • आपका ईमेल पता
  • आपके पासवर्ड का bcrypt हैश (कॉस्ट फ़ैक्टर 12 — सीधे उपयोग करने योग्य नहीं)
  • PBKDF2 सॉल्ट
  • रैप किया हुआ KEK
  • आपके हर डॉक्यूमेंट के लिए रैप की गई FK
  • हर डॉक्यूमेंट के लिए एन्क्रिप्टेड ब्लॉब

एक भी डॉक्यूमेंट डिक्रिप्ट करने के लिए, हमलावर को यह करना होगा:

  1. bcrypt हैश से आपका पासवर्ड क्रैक करें (या PBKDF2 सॉल्ट से अनुमान लगाएँ, जो पासवर्ड अनुमान को सार्थक रूप से तेज़ नहीं करता)
  2. मास्टर की डिराइव करने के लिए क्रैक किए गए पासवर्ड + सॉल्ट का उपयोग करके 600,000 इटरेशन पर PBKDF2 चलाएँ
  3. KEK अनरैप करने के लिए मास्टर की का उपयोग करें
  4. लक्षित डॉक्यूमेंट के लिए FK अनरैप करने के लिए KEK का उपयोग करें
  5. एन्क्रिप्टेड ब्लॉब डिक्रिप्ट करने के लिए FK का उपयोग करें

हर चरण के लिए पिछले चरण के सफलतापूर्वक पूरा होने की आवश्यकता होती है। PBKDF2 की लागत को इस तरह डिज़ाइन किया गया है कि चरण 2 हर अनुमान के लिए सार्थक कंप्यूट समय ले, जिससे मज़बूत पासवर्ड के विरुद्ध ब्रूट-फ़ोर्स अटैक अव्यावहारिक हो जाते हैं।

पूर्ण ब्रीच मेटाडेटा उजागर करता है लेकिन कंटेंट नहीं। यही ज़ीरो-नॉलेज आर्किटेक्चर की व्यावहारिक गारंटी है। PDF एडिटिंग में प्राइवेसी प्रथाओं के व्यापक अवलोकन के लिए हमारी PDF प्राइवेसी गाइड देखें।

अधिक पढ़ने के लिए

इस कार्यान्वयन के पीछे Web Crypto API, PBKDF2, और AES-GCM की विशिष्टताएँ:

RedaktPDF आज़माने के लिए तैयार हैं?

अपने ब्राउज़र में सीधे PDF संपादित करें, रिडैक्ट करें और एनोटेट करें — मुफ़्त और एन्क्रिप्टेड।

शुरू करें

संबंधित टूल्स

संबंधित लेख