आज हम Product Hunt पर हैं! टिप्पणी लिखें

Authenticator 1.16.0 आ गया है। देखें क्या नया है

यह कैसे काम करता है

सुरक्षा की समीक्षा करने वालों के लिए तकनीकी विवरण। यहाँ लिखी हर बात स्रोत कोड से मिलाकर जाँची जा सकती है — उन हिस्सों समेत जो हमारे पक्ष में नहीं हैं और जिन्हें हम छिपाने के बजाय साफ़ लिखते हैं।

आर्किटेक्चर

यह एक Manifest V3 क्रोम एक्सटेंशन है जो TOTP कोड OTPAuth की मदद से डिवाइस पर ही बनाता है। कोड बनाने, खाते सहेजने और उन्हें एन्क्रिप्ट करने में कोई बैकएंड शामिल नहीं है, और हमारे यहाँ कोई उपयोगकर्ता खाता नहीं बनता। मुफ़्त प्लान और Pro के लिए हम एक सर्वर चलाते हैं, api.authenticator.sh — इसका विवरण नीचे है — और उस तक कभी कोई गुप्त कुंजी, खाते का नाम, जारीकर्ता या कोड नहीं पहुँचता।

उस सर्वर के पास किसी के भी खातों की कोई कुंजी सामग्री नहीं होती: न कुंजी एस्क्रो है, न हमारे नियंत्रण वाला कोई रिकवरी रास्ता। यदि उपयोगकर्ता पासवर्ड भूल जाए और रिकवरी कोड भी खो दे, तो हम कुछ नहीं कर सकते — यह डिज़ाइन का हिस्सा है।

क्रिप्टोग्राफ़ी

पासवर्ड सुरक्षा वैकल्पिक है और डिफ़ॉल्ट रूप से बंद रहती है। चालू होने पर:

सिफर
AES-256-GCM, हर रिकॉर्ड और हर बार दोबारा लिखने पर यादृच्छिक 96-बिट IV
कुंजी व्युत्पत्ति
PBKDF2-HMAC-SHA256, 6,00,000 पुनरावृत्तियाँ, यादृच्छिक 128-बिट सॉल्ट (OWASP की सलाह के अनुसार)
मास्टर कुंजी
256-बिट, crypto.getRandomValues से, एक ही बार बनती है; पासवर्ड सिर्फ़ उसे लपेटता है
फ़िंगरप्रिंट
HKDF से बनी उप-कुंजी पर HMAC-SHA256, जिससे रिकॉर्ड अलग-अलग डिवाइसों के बीच मिलाए जाते हैं
अनलॉक कुंजी का भंडारण
chrome.storage.session — केवल मेमोरी में, डिस्क पर कभी नहीं लिखी जाती, ब्राउज़र बंद होते ही मिट जाती है, और कंटेंट स्क्रिप्ट की पहुँच से बाहर रहती है
स्वतः लॉक
हर बार खोलने पर / 5, 15 या 60 मिनट निष्क्रियता के बाद / ब्राउज़र बंद होने तक
क्रियान्वयन
केवल WebCrypto। कोई भी प्रिमिटिव हाथ से नहीं लिखा गया और कोई क्रिप्टो लाइब्रेरी पैकेज में शामिल नहीं है।

कुंजी के दो स्तर क्यों

डेटा को पासवर्ड से बनी कुंजी से सीधे कभी एन्क्रिप्ट नहीं किया जाता। रिकॉर्ड एक यादृच्छिक मास्टर कुंजी से एन्क्रिप्ट होते हैं; PBKDF2 का आउटपुट सिर्फ़ उस मास्टर कुंजी को लपेटता है। इससे दो नतीजे निकलते हैं, और दोनों मायने रखते हैं:

  • पासवर्ड बदलने पर हर रिकॉर्ड, हर बैकअप और हर एक्सपोर्ट को दोबारा एन्क्रिप्ट करने के बजाय सिर्फ़ 32 बाइट दोबारा लिखे जाते हैं। भंडारण व्यवस्थाएँ डेटा ठीक ऐसे ही थोक लेखन के दौरान गँवाती हैं।
  • 160-बिट का रिकवरी कोड उसी मास्टर कुंजी को स्वतंत्र रूप से लपेट सकता है, इसलिए भूला हुआ पासवर्ड वापस पाया जा सकता है। कोड एक ही बार दिखता है, पुष्टि के लिए उसे दोबारा टाइप करना पड़ता है, और हर इस्तेमाल के बाद वह बदल जाता है। जब तक उपयोगकर्ता उसकी पुष्टि न कर दे, डिस्क पर कुछ नहीं लिखा जाता।

क्या एन्क्रिप्ट होता है और क्या नहीं

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

साफ़-साफ़ कह रहे हैं, क्योंकि आपके आकलन के लिए यह अहम है:

  • पासवर्ड सुरक्षा बंद होने पर खाते बिना एन्क्रिप्शन के सहेजे जाते हैं और, यदि Chrome Sync चालू है, तो उपयोगकर्ता के अपने Google खाते के ज़रिए दोहराए जाते हैं। वे हम तक कभी नहीं पहुँचते, पर Google के पास रहते हैं। सिंक बंद किया जा सकता है, जिससे वहाँ पहले से मौजूद डेटा भी हट जाता है।
  • प्रति-साइट उपयोग इतिहास — कौन-सा खाता किस डोमेन पर इस्तेमाल होता है — स्थानीय रूप से सहेजा जाता है और जब तक इकट्ठा हो रहा है, तिजोरी के दायरे में नहीं आता। पासवर्ड सुरक्षा चालू करने पर यह मिट जाता है; इसे अलग से भी बंद किया जा सकता है।

ख़तरा मॉडल

इनसे बचाता है

  • ब्राउज़र की प्रोफ़ाइल डायरेक्टरी चोरी होना या कॉपी हो जाना
  • इन्फ़ोस्टीलर मैलवेयर जो ब्राउज़र का डेटा थोक में बाहर भेजता है
  • बिना निगरानी छोड़ी गई मशीन तक किसी की भौतिक पहुँच
  • Chrome Sync के ज़रिए खातों के रिकॉर्ड का Google तक पहुँचना
  • बैकअप फ़ाइल का खो जाना या चोरी होना (पासवर्ड-सुरक्षित एक्सपोर्ट)

इनसे नहीं बचाता

  • तिजोरी अनलॉक रहते हुए उपयोगकर्ता के रूप में चल रहा मैलवेयर
  • टाइप करते समय पासवर्ड पकड़ने वाला कीलॉगर
  • पहले से समझौता किया जा चुका ब्राउज़र या ऑपरेटिंग सिस्टम
  • उन तृतीय-पक्ष सेवाओं में सेंध, जिनके लिए ये कोड हैं
  • बिना एन्क्रिप्शन का निर्यात जो आपने खुद लिखा — सादा JSON, otpauth:// लिंक या CXF को कोई भी पढ़ सकता है जो फ़ाइल खोले

संक्षेप में: यह निष्क्रिय अवस्था में रखे डेटा की रक्षा करता है। जो डिवाइस इस्तेमाल के समय पहले से ही हमलावर के नियंत्रण में है, उसकी रक्षा यह नहीं करता, और कर भी नहीं सकता।

अनुमतियाँ

मैनिफ़ेस्ट पाँच अनुमतियाँ घोषित करता है और कोई होस्ट अनुमति नहीं:

storage
खाते और सेटिंग्स लोकल स्टोरेज में, अनलॉक कुंजी सेशन स्टोरेज में, और वैकल्पिक सिंक प्रति
activeTab
मेल खाते खाते को उभारने के लिए सक्रिय टैब का होस्टनाम पढ़ता है, और जब उपयोगकर्ता स्क्रीन से QR कोड स्कैन करता है तो उस टैब को कैप्चर करता है
contextMenus
राइट-क्लिक मेन्यू में “2FA कोड डालें” आइटम जोड़ता है, और केवल http(s) पेजों के संपादन-योग्य फ़ील्ड पर
scripting
कोड को फ़ील्ड में डालने वाला एक ही फ़ंक्शन इंजेक्ट करता है — एक टैब और एक ही बार के लिए, और तभी जब वह मेन्यू आइटम चुना गया हो
sidePanel
जब वही सतह चुनी गई हो तो ऐप को Chrome के साइड पैनल में खोलता है; इससे किसी पेज तक पहुँच नहीं मिलती

यहाँ कोई कंटेंट स्क्रिप्ट नहीं है हैं, tabs, cookies या webRequest अनुमतियाँ नहीं हैं, और कोई web-accessible resources नहीं हैं। जब तक आप वहाँ कोड नहीं माँगते, किसी पेज पर हमारा कुछ भी मौजूद नहीं होता; उस समय जो चलता है वह उसी एक टैब और उसी एक बार के लिए इंजेक्ट होता है, उसी अनुमति के तहत जो आपका अपना क्लिक देता है, और पीछे कुछ नहीं छोड़ता।

कैमरा

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

मुफ़्त प्लान, Pro और रोज़ाना का संपर्क

1.14.0 से एक्सटेंशन दिन में एक बार api.authenticator.sh से संपर्क करता है — ब्राउज़र शुरू होने पर, या पॉपअप दिख जाने के बाद; कोड दिखाने के रास्ते में कभी नहीं। अनुरोध में फ़ील्ड की एक तय, बंद सूची होती है, जो src/billing/sync.ts के एक ही फ़ंक्शन में बनती है, और एक टेस्ट उसे इसी सूची तक सीमित रखता है:

iid
इस इंस्टॉलेशन द्वारा बनाई गई एक यादृच्छिक ID। Google खाते, ईमेल पते या ब्राउज़र से जुड़ी नहीं — जब तक उपयोगकर्ता Pro न ख़रीदे: तब ख़रीद का रिकॉर्ड उस इंस्टॉलेशन को जिससे ख़रीदा गया, और हर उस इंस्टॉलेशन को जिस पर लाइसेंस कुंजी सक्रिय है, भुगतान वाले ईमेल पते से जोड़ देता है
ver, ui_lang, browser_lang
एक्सटेंशन का संस्करण, इंटरफ़ेस की भाषा, ब्राउज़र की भाषा
installed_at, legacy, legacy_src
इंस्टॉलेशन कब हुआ, और क्या वह बिलिंग आने से पहले का है
accounts, groups
उसमें कितने खाते हैं और वे कितने समूहों में हैं — सिर्फ़ संख्याएँ, कौन-से खाते या समूहों के नाम कभी नहीं
vault, sync, open_mode, view_mode, style, dark, os
पासवर्ड सुरक्षा और सिंक चालू हैं या नहीं, और एक्सटेंशन कैसे खुलता है, खातों की सूची कैसे दिखती है (सामान्य, कॉम्पैक्ट या छिपे कोड के साथ), और कौन-सी शैली चुनी गई है, हल्की या गहरी, और ऑपरेटिंग सिस्टम (Windows, macOS, Linux, ChromeOS)
pid, lid, has_key, key_hint
इंस्टॉलेशन के पास इस समय कौन-सी हस्ताक्षरित नीति और कौन-सा लाइसेंस है, लाइसेंस कुंजी उसके पास पहले से है या नहीं, और उस कुंजी के आख़िरी चार अक्षर
opens
पिछले संपर्क के बाद से हर दिन एक्सटेंशन कितनी बार खोला गया (ज़्यादा से ज़्यादा पिछले 14 दिन) — हर दिन की सिर्फ़ एक गिनती, क्या देखा गया इसके बारे में कुछ नहीं
events
एक बंद सूची में से कतार में रखी बिलिंग घटनाएँ: सीमा पूरी हुई, पेवॉल दिखाया या बंद किया गया, कोई प्लान चुना गया, चेकआउट या कुंजी आज़माई गई

कभी नहीं भेजा जाता: गुप्त कुंजियाँ, खातों के नाम, जारीकर्ता, कोड, या वे साइटें जिन पर उनका इस्तेमाल होता है। सर्वर अपने एज पर अनुरोध से देश लेता है और IP पता सहेजता नहीं। अनइंस्टॉल पेज को वही इंस्टॉल ID ?i= के रूप में मिलती है: वह सर्वर को बताता है कि इंस्टॉलेशन हटा दिया गया है, और वैकल्पिक सर्वे का जवाब उसी इंस्टॉलेशन से जोड़ता है।

इसके लिए chrome.storage.local में रखा जाता है: इंस्टॉल ID, आख़िरी हस्ताक्षरित नीति और लाइसेंस, इस इंस्टॉलेशन के पास मौजूद लाइसेंस कुंजी (टाइप की हुई, या इसी पर ख़रीदने के बाद मिली), सर्वर तक पहुँचने तक हर दिन खोले जाने की गिनती, और कतार में रखी घटनाएँ — खातों का कोई डेटा नहीं। सिंक चालू रहने पर, इंस्टॉलेशन बिलिंग से पहले का है या नहीं — यह जानकारी और वही लाइसेंस कुंजी भी Chrome Sync में जाती हैं, ताकि उपयोगकर्ता की दूसरी Chrome प्रोफ़ाइलें उन्हें ले लें और Pro अपने-आप चालू कर दें; सिंक बंद करने पर दोनों Chrome Sync से हट जाती हैं, और फिर चालू करने पर वापस आ जाती हैं।

क्या वापस आता है, और एक्सटेंशन उसके साथ क्या करता है:

टोकन
नीति (मुफ़्त प्लान में खातों की सीमा) और लाइसेंस (Pro) ES256 (ECDSA P-256) से हस्ताक्षरित JWS हैं
सत्यापन
WebCrypto से, बिल्ड में कंपाइल की गई सार्वजनिक कुंजियों के आधार पर (src/billing/keys.ts)। Chrome Web Store का बिल्ड सिर्फ़ प्रोडक्शन कुंजी पर भरोसा करता है, और बिल्ड जाँच ऐसे किसी भी बिल्ड को अस्वीकार कर देती है जिसमें कोई दूसरी कुंजी हो
ऑफ़लाइन
सीमा और लाइसेंस डिवाइस पर ही, आख़िरी हस्ताक्षरित टोकन से जाँचे जाते हैं। जब तक कोई हस्ताक्षरित नीति नहीं मिली, कोई सीमा नहीं लगती — पहुँच से बाहर सर्वर कभी किसी को बाहर लॉक नहीं कर सकता
सीमा क्या कर सकती है
किसी खाते को जुड़ने से रोकना, और कुछ नहीं। वह किसी खाते को छिपा, लॉक, हटा या बदल नहीं सकती, और न ही कोड, निर्यात, बैकअप, पुनर्स्थापना या सिंक रोक सकती है
खरीदारी
नए टैब में Stripe Checkout, जिसमें Link आधिकारिक विक्रेता (merchant of record) है। ख़रीदार का ईमेल हमें Stripe से मिलता है, ताकि लाइसेंस कुंजी जारी की जा सके और खो जाने पर वापस मिल सके; कुंजियाँ हैश के रूप में सहेजी जाती हैं, साथ में एक एन्क्रिप्टेड प्रति, ताकि खोई हुई कुंजी दोबारा भेजी जा सके
लाइसेंस कुंजी
रोज़ाना संपर्क के जवाब में कुंजी ख़ुद सिर्फ़ उस इंस्टॉलेशन को भेजी जाती है जिस पर Pro ख़रीदा गया, और तभी तक जब तक key_hint में बताए गए उसके चार अक्षर उस कुंजी से मेल न खा जाएँ — इसलिए बाद में ख़रीदी गई कुंजी पुरानी कुंजी की जगह ले लेती है; जिस इंस्टॉलेशन में कुंजी टाइप की गई हो, उसे यह कभी नहीं भेजी जाती

यह सीमा DRM नहीं है: कोड ओपन सोर्स है, और कोई फ़ोर्क इसे हटा सकता है। जो कभी संभव नहीं होना चाहिए, वह है किसी व्यक्ति का किसी दूसरे का लाइसेंस हासिल करना या इस्तेमाल करना, या किसी और के इंस्टॉलेशन पर सीमा लगवा देना — यह एक सुरक्षा खामी है, और हमारी सुरक्षा नीति के दायरे में आती है।

बाहर जाने वाला नेटवर्क ट्रैफ़िक

दो तरह के अनुरोध अपने आप होते हैं: घड़ी की जाँच और रोज़ाना का बिलिंग संपर्क। नीचे बाकी सब कुछ तभी होता है जब उपयोगकर्ता खुद कहीं क्लिक करता है। Manifest V3 रिमोट कोड पर रोक लगाता है, और इनमें से कोई भी खाते, गुप्त कुंजियाँ या बने हुए कोड नहीं ले जाता। पूरी सूची:

होस्टकबक्या उपयोगकर्ता डेटा जाता है?
time.akamai.com
timeapi.io
cloudflare.com
घड़ी के अंतर की जाँच, कैश के साथ; कोई भी स्रोत न मिले तो सेटिंग्स में यह लिखा होता है। घड़ी खिसकी हो तो TOTP टूट जाता है।नहीं
authenticator.shइंस्टॉल पर स्वागत पेज; अनइंस्टॉल पर प्रतिक्रिया पेज, जिसके पते में इंस्टॉल ID होती है; पॉपअप से खोले जाने पर सहायता और सपोर्ट पेज।इंस्टॉल ID, सिर्फ़ अनइंस्टॉल पेज पर; बाकी समय नहीं (सामान्य वेब सर्वर लॉग)
api.authenticator.shदिन में एक बार बिलिंग संपर्क; चेकआउट, लाइसेंस और पोर्टल अनुरोध, जब उपयोगकर्ता Pro खरीदता है, कुंजी डालता है, खरीदारी पुनर्स्थापित करता है या सदस्यता प्रबंधित करता है।ऊपर बताए गए फ़ील्ड — खातों का डेटा कभी नहीं। लाइसेंस कुंजी या ईमेल पता सिर्फ़ तब, जब उपयोगकर्ता खुद उसे टाइप करे
checkout.stripe.com
billing.stripe.com
Stripe Checkout और कस्टमर पोर्टल, जो उपयोगकर्ता के Pro खरीदने या सदस्यता प्रबंधित करने पर एक टैब में खुलते हैं।जो ख़रीदार वहाँ डालता है। Stripe और Link की अपनी शर्तें लागू होती हैं
chromewebstore.google.comस्टोर लिस्टिंग, क्लिक करने पर ही नए टैब में: रेटिंग के संकेत से समीक्षा फ़ॉर्म।नहीं (Google को यह किसी भी दूसरे स्टोर पेज जैसी ही विज़िट दिखती है)

कोई फ़ॉन्ट, स्क्रिप्ट, स्टाइल या छवि तृतीय-पक्ष होस्ट से लोड नहीं होती। इंटरफ़ेस दिखाने के लिए जो भी चाहिए, वह पैकेज के भीतर ही आता है।

हम जो प्रकाशित करते हैं उसे जाँचना

ऊपर लिखी किसी भी बात को भरोसे पर मानने की ज़रूरत नहीं। एक्सटेंशन ओपन सोर्स है और हर रिलीज़ दोबारा बनाई जा सकती है:

  1. Chrome Web Store से प्रकाशित .crx डाउनलोड करके उसे अनज़िप करें
  2. उससे मेल खाते git टैग पर जाएँ
  3. Node 20 LTS पर npm ci && npm run build चलाएँ
  4. बनी हुई dist/ की तुलना अनज़िप किए पैकेज से करें

बनी हुई dist/ की हर फ़ाइल का SHA-256 हर GitHub रिलीज़ के साथ SHA256SUMS-v<version>.txt नाम से, sha256sum प्रारूप में प्रकाशित होता है — इसलिए चरण 4 सिर्फ़ एक बार sha256sum -c चलाने जितना रह जाता है। अंतर केवल आर्काइव के भीतर फ़ाइलों के क्रम और Node की अलग पैच रिलीज़ में मिनिफ़ाइड आउटपुट के ख़ाली स्थान तक सीमित होने चाहिए।

रनटाइम निर्भरताएँ जानबूझकर बहुत कम हैं — OTPAuth, React, jsQR, Zustand, Framer Motion और Lucide — और कमिट की गई लॉकफ़ाइल से तय हैं। CycloneDX प्रारूप में SBOM माँगने पर उपलब्ध है।

स्रोत कोड देखें

जो हमारे पास नहीं है

हम एक छोटे स्वतंत्र विक्रेता हैं। यदि नीचे में से कुछ भी आपकी प्रक्रिया के लिए अनिवार्य है, तो मूल्यांकन के तीन हफ़्ते बाद पता चलने से बेहतर है कि अभी पता चल जाए:

  • SOC 2, ISO 27001 या इनके समकक्ष कोई प्रमाणन नहीं
  • आज तक किसी तृतीय-पक्ष पेनिट्रेशन टेस्ट का आदेश नहीं दिया गया
  • कोई सशुल्क बग बाउंटी कार्यक्रम नहीं

इनके बदले हम जो देते हैं वह है स्रोत कोड की पूरी पारदर्शिता, जाँची जा सकने वाली बिल्ड, न्यूनतम अनुमतियाँ, और एक ऐसा सर्वर जिसे आपकी गुप्त कुंजियाँ, खातों के नाम या कोड भेजे ही नहीं जाते।

हमसे बात करना

सुरक्षा खामियों की सूचना और सुरक्षा से जुड़े सवाल: security@authenticator.sh। हमारी प्रकटीकरण नीति, दायरा, प्रतिक्रिया समय और सेफ़ हार्बर शर्तें सुरक्षा नीति पेज पर हैं; क्या सहेजा जाता है और डिवाइस से क्या बाहर जाता है, यह गोपनीयता नीति में लिखा है।

हम विक्रेता आकलन की लिखित प्रश्नावली भरने या किसी सुरक्षा टीम के साथ कोड पर चलकर बात करने को तैयार हैं।

जो कुछ भी सुरक्षा का मामला नहीं है — इंस्टॉलेशन, खाता वापस पाना, तैनाती से जुड़े बिलिंग सवाल — उसके लिए सहायता देखें। कृपया सुरक्षा खामियों की सूचना वहाँ न भेजें; वह इनबॉक्स गोपनीय नहीं माना जाता।