PDF Pro की क्रिप्टोग्राफ़िक प्रणाली का विस्तृत तकनीकी दस्तावेज़ीकरण
एंड-टू-एंड एन्क्रिप्टेड फ़ाइल ट्रांसफर
PDF Pro श्वेतपत्र WP-001 — आर्किटेक्चर और सुरक्षा
यह श्वेतपत्र PDF Pro की Secure Transfer प्रणाली के आर्किटेक्चर का वर्णन करता है — यह एक एंड-टू-एंड एन्क्रिप्टेड फ़ाइल ट्रांसफर तंत्र है जिसमें फ़ाइलें अपलोड से पहले AES-256-GCM का उपयोग करके क्लाइंट-साइड एन्क्रिप्ट की जाती हैं। सर्वर केवल अपारदर्शी सिफरटेक्स्ट संग्रहीत करता है और किसी भी बिंदु पर फ़ाइल सामग्री को डिक्रिप्ट, निरीक्षण या पढ़ने में सक्षम नहीं होता। यह प्रणाली दो मुख्य मोड का समर्थन करती है: एक स्वतः-उत्पन्न यादृच्छिक कुंजी (URL फ्रैगमेंट के माध्यम से परिवहित, जो कभी सर्वर को नहीं भेजी जाती) या PBKDF2 का उपयोग करके पासफ्रेज़-व्युत्पन्न कुंजी। दोनों मोड में, एन्क्रिप्शन कुंजी केवल प्रेषक और प्राप्तकर्ता के ब्राउज़र में मौजूद रहती है। यह दस्तावेज़ प्रणाली के क्रिप्टोग्राफ़िक प्रिमिटिव, डेटा प्रवाह, खतरे के मॉडल और ईमानदार सीमाओं का विवरण देता है। शब्दावली पर नोट: यह प्रणाली जीरो-नॉलेज प्रूफ (ZKPs) का उपयोग नहीं करती। जब हम कहते हैं कि सर्वर को आपकी फ़ाइलों की "शून्य जानकारी" है, तो हमारा तात्पर्य है — क्लाइंट-साइड एन्क्रिप्शन के परिणामस्वरूप — सर्वर केवल ऐसा सिफरटेक्स्ट रखता है जिसे वह डिक्रिप्ट नहीं कर सकता।
Secure Transfer प्रणाली एक सख्त क्लाइंट-सर्वर पृथक्करण का पालन करती है जहाँ सभी क्रिप्टोग्राफ़िक संक्रियाएँ विशेष रूप से ब्राउज़र में होती हैं:
सर्वर को जानबूझकर एन्क्रिप्टेड डेटा के लिए एक "डम्ब पाइप" के रूप में डिज़ाइन किया गया है। उसे एन्क्रिप्शन कुंजी, पासफ्रेज़ या फ़ाइल सामग्री का कोई ज्ञान नहीं है। यह आर्किटेक्चरल रूप से लागू है, न केवल नीति द्वारा।
डिज़ाइन सिद्धांत: सर्वर से समझौता होने पर भी उपयोगकर्ता डेटा से समझौता न हो। पूर्ण डेटाबेस एक्सेस और सर्वर-साइड कोड निष्पादन के साथ भी, कोई हमलावर ट्रांसफर की गई फ़ाइलों को डिक्रिप्ट नहीं कर सकता।
सभी फ़ाइल एन्क्रिप्शन AES-256-GCM प्रमाणित एन्क्रिप्शन एल्गोरिदम का उपयोग करता है, जो ब्राउज़र के नेटिव Web Crypto API के माध्यम से एक्सेस किया जाता है। यह गोपनीयता (डेटा पढ़ा नहीं जा सकता) और अखंडता (बिना पहचान के डेटा संशोधित नहीं किया जा सकता) दोनों प्रदान करता है।
| पैरामीटर | मान | औचित्य |
|---|---|---|
| एल्गोरिदम | AES-256-GCM | NIST-अनुमोदित, संबद्ध डेटा के साथ प्रमाणित एन्क्रिप्शन (AEAD) |
| कुंजी आकार | 256 बिट | अधिकतम AES कुंजी लंबाई; ब्रूट फोर्स के विरुद्ध 128-बिट सुरक्षा प्रदान करती है |
| IV आकार | 96 बिट (12 बाइट) | GCM मोड के लिए NIST-अनुशंसित IV लंबाई |
| टैग आकार | 128 बिट (16 बाइट) | अधिकतम अखंडता सुरक्षा के लिए पूर्ण-लंबाई प्रमाणीकरण टैग |
| IV उत्पादन | crypto.getRandomValues() | क्रिप्टोग्राफ़िक रूप से सुरक्षित यादृच्छिक संख्या जनरेटर |
// Simplified encryption flow (Web Crypto API) const iv = crypto.getRandomValues(new Uint8Array(12)); const salt = crypto.getRandomValues(new Uint8Array(16)); // Derive key from passphrase (see Section 1.4) const key = await deriveKey(passphrase, salt); // Encrypt the file const ciphertext = await crypto.subtle.encrypt( { name: "AES-GCM", iv: iv }, key, fileArrayBuffer ); // Package: [salt (16B)] + [iv (12B)] + [ciphertext + tag] const blob = concatenate(salt, iv, ciphertext);
अंतिम एन्क्रिप्टेड ब्लॉब तीन घटकों का संयोजन है: 16-बाइट सॉल्ट (कुंजी व्युत्पत्ति के लिए उपयोग), 12-बाइट IV (AES-GCM के लिए उपयोग), और संलग्न 16-बाइट GCM प्रमाणीकरण टैग के साथ सिफरटेक्स्ट। यही ब्लॉब सर्वर को प्राप्त होता है और संग्रहीत किया जाता है।
Secure Transfer दो परस्पर अनन्य कुंजी मोड का समर्थन करता है। मोड का चयन प्रेषक द्वारा ट्रांसफर निर्माण के समय किया जाता है।
डिफ़ॉल्ट मोड में, कोई पासफ्रेज़ शामिल नहीं होता। ब्राउज़र सीधे एक क्रिप्टोग्राफ़िक रूप से यादृच्छिक 256-बिट AES कुंजी उत्पन्न करता है:
crypto.getRandomValues() और crypto.subtle.generateKey() के माध्यम से एक यादृच्छिक 256-बिट AES-GCM कुंजी उत्पन्न करता है।#) में रखा जाता है।जब प्रेषक पासफ्रेज़ सेट करने का विकल्प चुनता है, तो PBKDF2 का उपयोग करके उस पासफ्रेज़ से कुंजी व्युत्पन्न की जाती है:
| पैरामीटर | मान | औचित्य |
|---|---|---|
| एल्गोरिदम | PBKDF2 | NIST SP 800-132 अनुशंसित; व्यापक रूप से ऑडिटेड |
| हैश फ़ंक्शन | SHA-256 | मानक क्रिप्टोग्राफ़िक हैश; 256-बिट आउटपुट |
| इटरेशन | 600,000 | PBKDF2-SHA256 के लिए OWASP 2023 अनुशंसा पूरी करता है |
| सॉल्ट आकार | 128 बिट (16 बाइट) | प्रति ट्रांसफर अद्वितीय; रेनबो टेबल अटैक को रोकता है |
| आउटपुट कुंजी लंबाई | 256 बिट | AES-256 कुंजी आवश्यकता से मेल खाती है |
async function deriveKey(passphrase, salt) { // Import passphrase as raw key material const keyMaterial = await crypto.subtle.importKey( "raw", new TextEncoder().encode(passphrase), { name: "PBKDF2" }, false, ["deriveKey"] ); // Derive AES-256-GCM key return crypto.subtle.deriveKey( { name: "PBKDF2", salt: salt, iterations: 600000, hash: "SHA-256" }, keyMaterial, { name: "AES-GCM", length: 256 }, false, ["encrypt", "decrypt"] ); }
सुरक्षा नोट: मोड B में सुरक्षा पासफ्रेज़ की एन्ट्रॉपी पर निर्भर करती है। हम 12+ वर्णों वाले पासफ्रेज़ की अनुशंसा करते हैं जिनमें अपरकेस, लोअरकेस, अंक और प्रतीक मिले हों।
एक सुरक्षित ट्रांसफर का पूर्ण जीवनचक्र इस मार्ग का अनुसरण करता है:
crypto.getRandomValues() का उपयोग करके एक यादृच्छिक 256-बिट AES-GCM कुंजी और एक यादृच्छिक 12-बाइट IV उत्पन्न करता है।#) में जोड़ता है।crypto.getRandomValues() का उपयोग करके एक यादृच्छिक 16-बाइट सॉल्ट और 12-बाइट IV उत्पन्न करता है।| डेटा तत्व | सर्वर को एक्सेस है? | विवरण |
|---|---|---|
| एन्क्रिप्टेड ब्लॉब (salt + IV + ciphertext + tag) | हाँ | अपारदर्शी बाइनरी डेटा; सर्वर सामग्री की व्याख्या नहीं कर सकता |
| ट्रांसफर ID | हाँ | ट्रांसफर पहचानकर्ता UUID v4 मान हैं जो PostgreSQL के gen_random_uuid() द्वारा उत्पन्न होते हैं, जो सर्वर के CSPRNG से 122 बिट क्रिप्टोग्राफ़िक यादृच्छिकता प्रदान करते हैं |
| मूल फ़ाइल नाम | हाँ | प्राप्तकर्ता को प्रदर्शित करने के लिए मेटाडेटा में संग्रहीत |
| मूल फ़ाइल आकार | हाँ | प्रदर्शन उद्देश्यों के लिए मेटाडेटा में संग्रहीत |
| समाप्ति टाइमस्टैम्प | हाँ | स्वतः-हटाने के प्रवर्तन के लिए उपयोग |
| डाउनलोड गिनती / सीमा | हाँ | बर्न-ऑन-रीड और डाउनलोड सीमा प्रवर्तन के लिए उपयोग |
| प्रेषक उपयोगकर्ता ID (यदि प्रमाणित) | हाँ | प्रबंधन के लिए ट्रांसफर को खाते से जोड़ता है |
| पासफ्रेज़ | नहीं — कभी नहीं | कभी सर्वर को नहीं भेजा जाता; कभी ब्राउज़र नहीं छोड़ता |
| व्युत्पन्न एन्क्रिप्शन कुंजी | नहीं — कभी नहीं | एन्क्रिप्ट/डिक्रिप्ट के दौरान केवल ब्राउज़र मेमोरी में मौजूद रहती है |
| प्लेनटेक्स्ट फ़ाइल सामग्री | नहीं — कभी नहीं | केवल एन्क्रिप्टेड सिफरटेक्स्ट ही सर्वर तक पहुँचता है |
| PBKDF2 इटरेशन गिनती | नहीं | क्लाइंट में हार्डकोडेड; सर्वर को प्रेषित नहीं |
डिज़ाइन के अनुसार सभी सुरक्षित ट्रांसफर क्षणिक हैं। स्थायी भंडारण का कोई विकल्प नहीं है।
| विकल्प | व्यवहार | प्रवर्तन |
|---|---|---|
| बर्न ऑन रीड | पहले सफल डाउनलोड के तुरंत बाद एन्क्रिप्टेड ब्लॉब हटा दिया जाता है | सर्वर-साइड: डाउनलोड स्ट्रीम पूरी होने के बाद स्टोरेज से ब्लॉब हटाया जाता है |
| 1 घंटा | डाउनलोड स्थिति की परवाह किए बिना 1 घंटे बाद स्वतः-हटाया जाता है | सर्वर-साइड: शेड्यूल्ड क्लीनअप जॉब + एक्सेस पर समाप्ति जाँच |
| 24 घंटे | 24 घंटे बाद स्वतः-हटाया जाता है | उपरोक्त के समान |
| 7 दिन | अधिकतम प्रतिधारण; 7 दिनों बाद स्वतः-हटाया जाता है | उपरोक्त के समान |
जब कोई ट्रांसफर समाप्त होता है या बर्न ऑन रीड होता है, तो एन्क्रिप्टेड ब्लॉब Supabase Storage से स्थायी रूप से हटा दिया जाता है। मेटाडेटा रिकॉर्ड को स्थायी रूप से हटाने से पहले 30 दिनों के लिए सॉफ्ट-डिलीटेड स्थिति में (दुरुपयोग जाँच के लिए) रखा जाता है। मेटाडेटा रिकॉर्ड में एन्क्रिप्शन कुंजी, पासफ्रेज़, या कोई भी ऐसी जानकारी नहीं होती जिसका उपयोग फ़ाइल को पुनर्निर्मित करने के लिए किया जा सके।
| खतरा | अटैक वेक्टर | शमन उपाय |
|---|---|---|
| सर्वर से समझौता | हमलावर को डेटाबेस और स्टोरेज तक पूर्ण पहुँच मिलती है | सभी संग्रहीत डेटा AES-256-GCM सिफरटेक्स्ट है। हमलावर को केवल अपारदर्शी ब्लॉब प्राप्त होते हैं। पासफ्रेज़ के बिना, 256-बिट AES को ब्रूट-फोर्स करना कम्प्यूटेशनल रूप से असंभव है। |
| नेटवर्क अवरोधन (MITM) | हमलावर ट्रांजिट में डेटा को इंटरसेप्ट करता है | सभी ट्रैफ़िक TLS 1.3 का उपयोग करता है। यदि TLS टूट जाती है, तो हमलावर को केवल एन्क्रिप्टेड ब्लॉब मिलते हैं (सर्वर समझौते के समान)। |
| कमज़ोर पासफ्रेज़ | हमलावर एक छोटे या सामान्य पासफ्रेज़ को ब्रूट-फोर्स करता है | 600K इटरेशन के साथ PBKDF2 प्रत्येक अनुमान को कम्प्यूटेशनल रूप से महंगा बनाता है। 4-वर्ण का पासफ्रेज़ भी महत्वपूर्ण कम्प्यूट की आवश्यकता होगी। UI न्यूनतम पासफ्रेज़ लंबाई लागू करता है और ताकत फ़ीडबैक प्रदान करता है। |
| पासफ्रेज़ अवरोधन | हमलावर प्रेषक और प्राप्तकर्ता के बीच साझा किए गए पासफ्रेज़ को इंटरसेप्ट करता है | पासफ्रेज़ आउट-ऑफ-बैंड साझा किया जाता है (हमारी प्रणाली के माध्यम से नहीं)। हम ट्रांसफर URL से अलग चैनल के माध्यम से साझा करने की अनुशंसा करते हैं। यह उपयोगकर्ता की जिम्मेदारी है। |
| क्लाइंट-साइड कोड टैम्परिंग | हमलावर उपयोगकर्ता को परोसे गए JavaScript को संशोधित करता है | सभी एसेट Vercel के CDN के साथ HTTPS पर परोसे जाते हैं। सबरिसोर्स इंटीग्रिटी (SRI) हैश CDN-स्तरीय टैम्परिंग से बचाते हैं। उपयोगकर्ता ब्राउज़र DevTools में सोर्स कोड सत्यापित कर सकते हैं। |
| मेमोरी एक्सट्रैक्शन | हमलावर ब्राउज़र मेमोरी से एन्क्रिप्शन कुंजी निकालता है | Web Crypto API कुंजियाँ जहाँ संभव हो नॉन-एक्सट्रैक्टेबल के रूप में चिह्नित हैं। व्युत्पन्न कुंजियाँ केवल एन्क्रिप्ट/डिक्रिप्ट ऑपरेशन के दौरान मेमोरी में मौजूद रहती हैं। ब्राउज़र मेमोरी आइसोलेशन OS-स्तरीय सुरक्षा प्रदान करता है। |
| रिप्ले अटैक | हमलावर एक कैप्चर किए गए एन्क्रिप्टेड ब्लॉब को रिप्ले करता है | प्रत्येक ट्रांसफर में एक अद्वितीय ID होता है और डाउनलोड सीमाओं तथा समाप्ति द्वारा सुरक्षित है। बर्न-ऑन-रीड ट्रांसफर पहली पहुँच के बाद हटा दिए जाते हैं। |
ईमानदार सीमाएँ: कोई भी सुरक्षा प्रणाली परिपूर्ण नहीं है। हम ज्ञात सीमाओं के पारदर्शी प्रकटीकरण में विश्वास करते हैं।
प्राइवेसी-फर्स्ट क्रिप्टोग्राफ़िक दस्तावेज़ हस्ताक्षर
PDF Pro श्वेतपत्र WP-002 — आर्किटेक्चर और सुरक्षा
यह श्वेतपत्र PDF Pro की Privacy Signature प्रणाली के आर्किटेक्चर का वर्णन करता है — यह एक क्रिप्टोग्राफ़िक दस्तावेज़ हस्ताक्षर तंत्र है जहाँ PDF दस्तावेज़ हस्ताक्षरकर्ता के ब्राउज़र को कभी नहीं छोड़ता। यह प्रणाली डिटैच्ड डिजिटल हस्ताक्षर उत्पन्न करने के लिए P-256 कर्व और SHA-256 हैशिंग के साथ ECDSA का उपयोग करती है। केवल दस्तावेज़ हैश, क्रिप्टोग्राफ़िक हस्ताक्षर और सार्वजनिक कुंजी सर्वर को प्रेषित की जाती हैं। निजी कुंजियाँ उत्पन्न, एन्क्रिप्ट और विशेष रूप से उपयोगकर्ता के ब्राउज़र में IndexedDB का उपयोग करके संग्रहीत की जाती हैं, जो PBKDF2 कुंजी व्युत्पत्ति (600,000 इटरेशन) और AES-256-GCM एन्क्रिप्शन द्वारा सुरक्षित हैं। यह दस्तावेज़ पूर्ण हस्ताक्षर और सत्यापन आर्किटेक्चर, कुंजी प्रबंधन मॉडल, हस्ताक्षरित पेलोड स्कीमा, ऑडिट ट्रेल डिज़ाइन, खतरे के मॉडल और ईमानदार सीमाओं का विवरण देता है।
Privacy Signature प्रणाली एक मूलभूत बाधा के इर्द-गिर्द डिज़ाइन की गई है: PDF दस्तावेज़ को कभी सर्वर को प्रेषित नहीं किया जाना चाहिए। यह डिटैच्ड सिग्नेचर मॉडल के माध्यम से आर्किटेक्चरल रूप से लागू है।
मुख्य गारंटी: सर्वर PDF दस्तावेज़ को कभी नहीं देखता, प्राप्त करता या संसाधित करता है। सर्वर को प्राप्त होने वाला एकमात्र दस्तावेज़-संबंधित डेटा SHA-256 हैश है — एक निश्चित-आकार 256-बिट मान जिससे मूल दस्तावेज़ को पुनर्निर्मित नहीं किया जा सकता।
| पैरामीटर | मान | औचित्य |
|---|---|---|
| हस्ताक्षर एल्गोरिदम | ECDSA (Elliptic Curve Digital Signature Algorithm) | NIST FIPS 186-4; कॉम्पैक्ट हस्ताक्षर; प्रति कुंजी बिट मज़बूत सुरक्षा |
| कर्व | P-256 (secp256r1 / prime256v1) | NIST-अनुमोदित; 128-बिट सुरक्षा स्तर; व्यापक Web Crypto API समर्थन |
| हैश फ़ंक्शन | SHA-256 | NIST FIPS 180-4; 256-बिट डाइजेस्ट; कोलिज़न-प्रतिरोधी |
| कुंजी आकार | 256-बिट निजी कुंजी, 512-बिट सार्वजनिक कुंजी (अनकम्प्रेस्ड) | P-256 के लिए मानक; ~3072-बिट RSA के समकक्ष |
| हस्ताक्षर आकार | 64 बाइट (r: 32 बाइट, s: 32 बाइट) | कॉम्पैक्ट; भंडारण और संचरण के लिए उपयुक्त |
| हस्ताक्षर प्रारूप | IEEE P1363 (raw r || s) | नेटिव Web Crypto API आउटपुट; भंडारण के लिए base64url-एन्कोडेड |
हस्ताक्षर एन्कोडिंग: P-256 के साथ Web Crypto API का ECDSA एक रॉ 64-बाइट हस्ताक्षर उत्पन्न करता है जिसमें बिग-एंडियन फिक्स्ड-विड्थ फॉर्मेट में दो 32-बाइट पूर्णांक (r || s) होते हैं। यह रॉ आउटपुट भंडारण के लिए base64url-एन्कोडेड है। यह DER-एन्कोडेड नहीं है — यह IEEE P1363 फॉर्मेट है जो Web Crypto API नेटिव रूप से उत्पन्न करता है।
// 1. Hash the PDF document (client-side) const fileBuffer = await file.arrayBuffer(); const hashBuffer = await crypto.subtle.digest("SHA-256", fileBuffer); const hashHex = Array.from(new Uint8Array(hashBuffer)) .map(b => b.toString(16).padStart(2, '0')).join(''); // 2. Sign the hash with the private key (client-side) const signature = await crypto.subtle.sign( { name: "ECDSA", hash: "SHA-256" }, privateKey, // CryptoKey from IndexedDB (decrypted) hashBuffer ); // 3. Send to server: hash + signature + public key (NOT the PDF) await submitSignature({ documentHash: hashHex, signature: base64Encode(signature), publicKey: exportedPublicKeyJWK });
| कुंजी प्रकार | संदर्भ | जीवनचक्र | भंडारण |
|---|---|---|---|
| एफिमेरल | गेस्ट उपयोगकर्ता (साइन इन नहीं) | प्रति सेशन उत्पन्न; टैब बंद होने पर नष्ट | केवल इन-मेमोरी (CryptoKey ऑब्जेक्ट); कभी परसिस्ट नहीं किया जाता |
| परसिस्टेंट | प्रमाणित उपयोगकर्ता (साइन इन) | एक बार उत्पन्न; सेशन के पार परसिस्ट; रिवोकेबल | IndexedDB (PBKDF2 + AES-256-GCM से एन्क्रिप्टेड) |
// Generate ECDSA P-256 key pair (Web Crypto API) const keyPair = await crypto.subtle.generateKey( { name: "ECDSA", namedCurve: "P-256" }, true, // extractable (needed for encryption + storage) ["sign", "verify"] ); // Export public key as JWK for server registration const publicKeyJWK = await crypto.subtle.exportKey("jwk", keyPair.publicKey); // Export private key as JWK for encrypted storage const privateKeyJWK = await crypto.subtle.exportKey("jwk", keyPair.privateKey);
सार्वजनिक कुंजी प्रारूप: सार्वजनिक कुंजियाँ JWK (JSON Web Key) प्रारूप में निर्यात और संग्रहीत की जाती हैं। कुंजी फिंगरप्रिंट केवल सार्वजनिक फ़ील्ड {crv, kty, x, y} युक्त कैनोनिकल JWK के SHA-256 के रूप में गणना किया जाता है, जिसमें कुंजियाँ वर्णानुक्रम में क्रमबद्ध होती हैं।
परसिस्टेंट निजी कुंजियाँ कभी प्लेनटेक्स्ट में संग्रहीत नहीं की जाती हैं। IndexedDB में लिखे जाने से पहले, निजी कुंजी (JWK JSON के रूप में निर्यातित) को Secure Transfer के समान पैटर्न का उपयोग करके एन्क्रिप्ट किया जाता है:
| पैरामीटर | मान |
|---|---|
| कुंजी व्युत्पत्ति | PBKDF2-SHA256, 600,000 इटरेशन |
| सॉल्ट | यादृच्छिक 16 बाइट (प्रति कुंजी) |
| एन्क्रिप्शन | AES-256-GCM |
| IV | यादृच्छिक 12 बाइट (प्रति एन्क्रिप्शन) |
| इनपुट | निजी कुंजी JWK (JSON स्ट्रिंग, UTF-8 एन्कोडेड) |
| IndexedDB में संग्रहीत आउटपुट | { salt, iv, ciphertext, publicKeyJWK, keyId, createdAt } |
// IndexedDB record structure for an encrypted signing key { "keyId": "uuid-v4-unique-identifier", "publicKey": { /* JWK format, unencrypted */ }, "encryptedPrivateKey": { "salt": "base64-encoded-16-bytes", "iv": "base64-encoded-12-bytes", "ciphertext": "base64-encoded-aes-gcm-ciphertext" }, "algorithm": "ECDSA", "curve": "P-256", "createdAt": "2026-04-16T00:00:00.000Z", "userId": "supabase-auth-user-id" }
कुंजी पुनर्प्राप्ति: यदि उपयोगकर्ता अपना हस्ताक्षर पासफ्रेज़ भूल जाता है, तो निजी कुंजी पुनर्प्राप्त नहीं की जा सकती। हमारे पास न पासफ्रेज़ है, न व्युत्पन्न कुंजी, और न ही PBKDF2 + AES-GCM सुरक्षा को बायपास करने का कोई तंत्र। उपयोगकर्ताओं को कुंजी बैकअप निर्यात करना चाहिए।
PDF Pro एक डिटैच्ड सिग्नेचर मॉडल का उपयोग करता है, जिसका अर्थ है कि हस्ताक्षर दस्तावेज़ से अलग संग्रहीत किया जाता है। यह महत्वपूर्ण गोपनीयता तंत्र है: दस्तावेज़ कभी हस्ताक्षरकर्ता के डिवाइस को नहीं छोड़ता।
क्रिप्टोग्राफ़िक आश्वासन: SHA-256 एक वन-वे हैश फ़ंक्शन है। केवल हैश e3b0c44298fc1c14... देखकर, यह ECDSA और SHA-256 की सुरक्षा धारणाओं के तहत मज़बूत क्रिप्टोग्राफ़िक आश्वासन प्रदान करता है कि मूल दस्तावेज़ को पुनर्निर्मित नहीं किया जा सकता। हैश दस्तावेज़ की सामग्री, लंबाई, या संरचना के बारे में कुछ भी प्रकट नहीं करता, केवल पुनः-हैश करने पर पहचान की पुष्टि करता है।
निम्नलिखित JSON स्कीमा सर्वर पर संग्रहीत पूर्ण हस्ताक्षर रिकॉर्ड को परिभाषित करती है:
{
"schemaVersion": "1.0",
"signatureId": "uuid-v4",
"documentHash": "sha256-hex-64-chars",
"hashAlgorithm": "SHA-256",
"signature": "base64-encoded-ecdsa-signature",
"signatureAlgorithm": "ECDSA",
"curve": "P-256",
"publicKey": {
"kty": "EC",
"crv": "P-256",
"x": "base64url-encoded-x-coordinate",
"y": "base64url-encoded-y-coordinate"
},
"signer": {
"identityLevel": "authenticated | self-asserted",
"displayName": "string or null",
"email": "string or null",
"userId": "supabase-uid or null"
},
"timestamp": "ISO-8601-UTC",
"metadata": {
"fileName": "original-file-name.pdf",
"fileSize": 123456,
"pageCount": 12,
"clientVersion": "2.0.0",
"userAgent": "browser-user-agent-string"
},
"auditChain": {
"previousEventHash": "sha256-of-previous-audit-event or null",
"eventHash": "sha256-of-this-record"
}
}हस्ताक्षर सत्यापन एक दो-चरण प्रक्रिया है: क्लाइंट-साइड क्रिप्टोग्राफ़िक सत्यापन के बाद सर्वर-साइड क्रॉस-चेकिंग।
const isValid = await crypto.subtle.verify( { name: "ECDSA", hash: "SHA-256" }, importedPublicKey, signatureBuffer, hashBuffer );
isValid === true, तो हस्ताक्षर क्रिप्टोग्राफ़िक रूप से वैध है: हस्ताक्षर के बाद से दस्तावेज़ संशोधित नहीं हुआ है, और हस्ताक्षर संबंधित निजी कुंजी के धारक द्वारा उत्पन्न किया गया था।| परिणाम | अर्थ |
|---|---|
| वैध (प्रमाणित) | हस्ताक्षर क्रिप्टोग्राफ़िक रूप से वैध है और सार्वजनिक कुंजी एक पंजीकृत, प्रमाणित PDF Pro उपयोगकर्ता की है। |
| वैध (स्व-अभिकथित) | हस्ताक्षर क्रिप्टोग्राफ़िक रूप से वैध है लेकिन हस्ताक्षरकर्ता की पहचान स्व-घोषित है (गेस्ट उपयोगकर्ता या असत्यापित नाम)। |
| अमान्य | क्रिप्टोग्राफ़िक सत्यापन विफल रहा। हस्ताक्षर के बाद से दस्तावेज़ संशोधित हो गया है, या हस्ताक्षर दूषित है। |
| रिवोक्ड | हस्ताक्षर वैध था लेकिन हस्ताक्षरकर्ता द्वारा स्पष्ट रूप से रिवोक कर दिया गया है। |
| कोई हस्ताक्षर नहीं मिला | इस दस्तावेज़ हैश के लिए कोई हस्ताक्षर रिकॉर्ड मौजूद नहीं है। |
प्रत्येक हस्ताक्षर और सत्यापन इवेंट एक टैम्पर-एविडेंट ऑडिट ट्रेल में दर्ज किया जाता है। इवेंट हैश-चेन्ड होते हैं: प्रत्येक इवेंट में पिछले इवेंट का SHA-256 हैश शामिल होता है, जो एक ब्लॉकचेन के समान एक अपेंड-ओनली चेन बनाता है।
| इवेंट प्रकार | ट्रिगर | दर्ज डेटा |
|---|---|---|
KEY_REGISTERED | उपयोगकर्ता नई सार्वजनिक कुंजी पंजीकृत करता है | सार्वजनिक कुंजी JWK, उपयोगकर्ता ID, टाइमस्टैम्प |
DOCUMENT_SIGNED | उपयोगकर्ता दस्तावेज़ पर हस्ताक्षर करता है | दस्तावेज़ हैश, हस्ताक्षर, सार्वजनिक कुंजी, हस्ताक्षरकर्ता पहचान, टाइमस्टैम्प |
SIGNATURE_VERIFIED | कोई भी उपयोगकर्ता हस्ताक्षर सत्यापित करता है | दस्तावेज़ हैश, सत्यापन परिणाम, सत्यापनकर्ता जानकारी (यदि प्रमाणित), टाइमस्टैम्प |
SIGNATURE_REVOKED | हस्ताक्षरकर्ता हस्ताक्षर रिवोक करता है | हस्ताक्षर ID, रिवोकेशन कारण, टाइमस्टैम्प |
KEY_REVOKED | उपयोगकर्ता सार्वजनिक कुंजी रिवोक करता है | सार्वजनिक कुंजी ID, रिवोकेशन कारण, टाइमस्टैम्प |
// Each audit event includes: { "eventId": "uuid-v4", "eventType": "DOCUMENT_SIGNED", "timestamp": "ISO-8601-UTC", "data": { /* event-specific payload */ }, "previousEventHash": "sha256-of-previous-event-json", "eventHash": "sha256-of-this-event-json-without-eventHash" } // Tamper detection: to verify the chain, compute: // SHA-256(JSON.stringify(event without eventHash field)) // and confirm it matches eventHash. // Then confirm previousEventHash matches the prior event's eventHash.
यदि चेन में कोई भी इवेंट संशोधित किया जाता है, तो सभी बाद के हैश लिंक टूट जाएंगे, जिससे टैम्परिंग तुरंत पहचाने योग्य हो जाती है। यह ऑडिट ट्रेल अखंडता की एक मज़बूत गारंटी प्रदान करता है।
महत्वपूर्ण सीमा: हैश चेन दर्ज इवेंट अनुक्रम के भीतर टैम्परिंग को पहचाने योग्य बनाती है। हालाँकि, डायरेक्ट एक्सेस वाला एक डेटाबेस एडमिनिस्ट्रेटर सैद्धांतिक रूप से चेन को हटा और पुनर्निर्माण कर सकता है। मज़बूत गारंटी के लिए बाहरी टाइमस्टैम्पिंग या तृतीय-पक्ष अनुप्रमाणन की आवश्यकता होगी, जो इस संस्करण में कार्यान्वित नहीं है।
| स्तर | आवश्यकताएँ | विश्वास गुण | उपयोग मामला |
|---|---|---|---|
| प्रमाणित | सत्यापित ईमेल के साथ साइन-इन PDF Pro उपयोगकर्ता; खाते में पंजीकृत परसिस्टेंट कुंजी जोड़ी | Supabase Auth द्वारा ईमेल सत्यापित; सार्वजनिक कुंजी प्रमाणित खाते से बाउंड; ऑडिट ट्रेल उपयोगकर्ता ID से लिंक | व्यावसायिक दस्तावेज़, अनुबंध, औपचारिक समझौते |
| स्व-अभिकथित | गेस्ट उपयोगकर्ता या स्व-दर्ज नाम वाला प्रमाणित उपयोगकर्ता; एफिमेरल या परसिस्टेंट कुंजी जोड़ी | क्रिप्टोग्राफ़िक अखंडता की गारंटी; हस्ताक्षरकर्ता पहचान स्व-घोषित और स्वतंत्र रूप से सत्यापित नहीं | त्वरित हस्ताक्षर, व्यक्तिगत दस्तावेज़, अनौपचारिक समझौते |
नोट: प्रोडक्ट UI में, 'self_asserted' को 'स्व-अभिकथित पहचान' या 'गेस्ट साइनिंग' के रूप में प्रदर्शित किया जा सकता है। 'authenticated' को 'प्रमाणित खाता' के रूप में प्रदर्शित किया जा सकता है। ये समान अंतर्निहित पहचान स्तरों के लिए प्रदर्शन लेबल हैं।
पहचान बाइंडिंग: एक "प्रमाणित" हस्ताक्षर का अर्थ है कि सार्वजनिक कुंजी एक सत्यापित ईमेल के साथ PDF Pro खाते में पंजीकृत है। इसका अर्थ यह नहीं है कि हस्ताक्षरकर्ता की वास्तविक दुनिया की पहचान सरकारी ID, बायोमेट्रिक्स, या व्यक्तिगत सत्यापन के माध्यम से सत्यापित की गई है। हम नो योर कस्टमर (KYC) जाँच नहीं करते।
| खतरा | अटैक वेक्टर | शमन उपाय |
|---|---|---|
| रिप्ले अटैक | हमलावर एक वैध हस्ताक्षर कॉपी करता है और इसे एक अलग दस्तावेज़ पर लागू करता है | हस्ताक्षर विशिष्ट दस्तावेज़ के SHA-256 हैश से बाउंड है। एक अलग दस्तावेज़ का अलग हैश होगा, और ECDSA सत्यापन विफल होगा। |
| जालसाज़ी | हमलावर निजी कुंजी के बिना एक वैध हस्ताक्षर बनाता है | ECDSA P-256 की सुरक्षा Elliptic Curve Discrete Logarithm Problem (ECDLP) पर आधारित है। निजी कुंजी के बिना हस्ताक्षर बनाना कम्प्यूटेशनल रूप से असंभव है (128-बिट सुरक्षा स्तर)। |
| कुंजी प्रतिस्थापन | हमलावर अपनी सार्वजनिक कुंजी पंजीकृत करता है और दावा करता है कि हस्ताक्षर किसी और ने किया | प्रमाणित हस्ताक्षर सार्वजनिक कुंजी को सत्यापित ईमेल से बाइंड करते हैं। ऑडिट ट्रेल रिकॉर्ड करता है कि किस कुंजी ने किस दस्तावेज़ पर हस्ताक्षर किया। कुंजी पंजीकरण इवेंट हैश-चेन्ड हैं। |
| दस्तावेज़ प्रतिस्थापन | हमलावर हस्ताक्षरित PDF को संशोधित करता है और दावा करता है कि हस्ताक्षर अभी भी वैध है | PDF में कोई भी संशोधन इसका SHA-256 हैश बदल देता है। मौजूदा हस्ताक्षर नए हैश के विरुद्ध सत्यापन में विफल होगा। एक कोलिज़न ढूँढना (समान हैश वाला अलग दस्तावेज़) ~2^128 संक्रियाओं की आवश्यकता होती है। |
| निजी कुंजी चोरी | हमलावर IndexedDB से एन्क्रिप्टेड निजी कुंजी निकालता है | निजी कुंजी AES-256-GCM से एन्क्रिप्टेड है, PBKDF2 (600K इटरेशन) द्वारा की-ड (keyed)। पासफ्रेज़ के बिना, कुंजी को डिक्रिप्ट करना कम्प्यूटेशनल रूप से असंभव है। |
| सर्वर से समझौता | हमलावर को पूर्ण सर्वर एक्सेस मिलती है | सर्वर के पास केवल सार्वजनिक कुंजियाँ और हस्ताक्षर रिकॉर्ड हैं। निजी कुंजियाँ कभी सर्वर तक नहीं पहुँचतीं। हमलावर नए हस्ताक्षर नहीं बना सकता। वे मौजूदा रिकॉर्ड हटा या संशोधित कर सकते हैं, लेकिन हैश-चेन टूटना पहचाने योग्य होगा। |
| ऑडिट ट्रेल टैम्परिंग | हमलावर सर्वर पर ऑडिट ट्रेल इवेंट संशोधित करता है | हैश-चेन्ड इवेंट: किसी भी इवेंट को संशोधित करने से उस बिंदु से आगे की चेन टूट जाती है। स्वतंत्र सत्यापन उपकरण चेन टूटना पहचान सकते हैं। |
PDF Pro हस्ताक्षर क्या नहीं हैं:
हमारी प्रतिबद्धता: हम आर्किटेक्चर के माध्यम से सुरक्षा बनाते हैं, न कि मार्केटिंग के माध्यम से। ये श्वेतपत्र वर्णन करते हैं कि हमारी प्रणालियाँ वास्तव में कैसे काम करती हैं, जिसमें उनकी सीमाएँ भी शामिल हैं। हम मानते हैं कि सुरक्षा-सचेत उपयोगकर्ता पूर्ण तकनीकी पारदर्शिता के हकदार हैं। यदि आपके हमारे आर्किटेक्चर के किसी भी पहलू के बारे में प्रश्न हैं, तो हमसे info@webdesign9.com पर संपर्क करें।