3 पॉइंट द्वारा GN⁺ 2025-05-24 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • लेखक ने ACME प्रोटोकॉल की जटिलता और implementation जोखिम की वजह से कई वर्षों तक इससे दूरी बनाए रखी
  • मौजूदा ACME clients में अक्सर security के लिहाज़ से जोखिमभरा या समझने में कठिन code था, इसलिए उन्हें सीधे चलाने में हिचक थी
  • लेकिन domain registrar Gandi की गुणवत्ता में गिरावट और कीमत बढ़ने के कारण खुद certificate renewal tool implement करना पड़ा
  • बहुत सारी कोशिशों और असफलताओं के बाद, Let's Encrypt के ज़रिए खुद certificate issue कराने वाला tool सफलतापूर्वक पूरा किया गया
  • लेख के बाद के हिस्से में ACME प्रोटोकॉल की वास्तविक कार्यप्रणाली और JSON, base64, signatures जैसी low-level implementation details को विस्तार से समझाया गया है

Why I no longer have an old-school cert on my https site

पृष्ठभूमि और वजह

  • 2023 की शुरुआत में पुराना प्रमाणपत्र बनाए रखने की वजह समझाई गई थी, लेकिन 2025 तक आते-आते अब उस तरीके को छोड़ने की वजह साझा की गई है
  • ACME प्रोटोकॉल के प्रति असहजता 2018 से थी, और जटिल web technologies तथा मुश्किल encoding तरीकों ने बड़ी बाधा पैदा की
  • ज़्यादातर ACME clients का code भरोसेमंद नहीं लगा, और उन्हें root privileges के साथ चलाना जोखिमभरा माना गया
  • Gandi के private equity द्वारा अधिग्रहण के बाद गुणवत्ता गिरी और कीमतें बढ़ीं, इसलिए पुराने प्रमाणपत्र को जारी रखने की कोई ठोस वजह नहीं बची

खुद implementation की शुरुआत

  • मौजूदा tools का इस्तेमाल करने के बजाय, लेखक ने खुद छोटे-छोटे utility functions से शुरुआत की
  • शुरुआत jansson नाम की C की JSON library को C++ में इस्तेमाल करने लायक wrap करने से हुई
  • JWK (Key struct) बनाने के लिए कई libraries देखीं, लेकिन ज़्यादातर मददगार नहीं रहीं, इसलिए इसे खुद implement करने का फैसला किया गया
  • बीच-बीच में कई बार रुककर फिर से शुरू करने की प्रक्रिया दोहराई गई, और धीरे-धीरे छोटे components को जोड़कर आगे बढ़ा गया

test environment और वास्तविक उपयोग

  • Let's Encrypt के असली servers को सीधे छूने से बचने के लिए, "pebble" नाम का test ACME server एक अलग environment में इस्तेमाल किया गया

  • अनगिनत असफलताओं के बाद, CSR इनपुट लेकर certificate issue करने वाला प्रारंभिक tool तैयार हो गया, और

    • Let's Encrypt staging server पर test सफल रहा
    • production environment में भी सफलता मिली
    • वास्तविक website पर भी इसे लागू कर दिया गया

ACME प्रोटोकॉल का विस्तृत विवरण

  • RSA key generate करके CN और SAN सहित CSR (Certificate Signing Request) बनाया जाता है
  • ACME directory URL से JSON parse करके newNonce, newAccount, newOrder जैसे endpoints निकाले जाते हैं
  • private key से modulus और public exponent निकाले जाते हैं, और उन्हें web के अनुकूल base64url encoding में बदला जाता है
  • JWK बनाने के बाद, JSON payload के साथ RSA SHA256 signature किया जाता है
  • HTTP HEAD request से Nonce लेकर, signed request को POST करके account बनाया जाता है
  • response का Location header वास्तविक redirect नहीं, बल्कि account identifier URL के रूप में इस्तेमाल होता है

ACME प्रोटोकॉल की जटिलता

  • सिर्फ certificate issue करने जैसे काम के बावजूद,
    • SHA256 hash, base64web, JSON के भीतर JSON संरचना, RSA signatures
    • HEAD request, Location header से account पहचान, one-time Nonce की ज़रूरत जैसी चीज़ें शामिल हैं
  • लेखक कहता है कि अभी तो certificate order, domain ownership proof (TXT record आदि), और validation completion जैसी चीज़ें अब तक ठीक से छुई भी नहीं गई हैं
  • कुछ clients में publicExponent encoding ग़लत होने पर भी काम चलता दिखा, इसलिए standard की ढील पर भी टिप्पणी की गई है

निष्कर्ष

  • ACME बेहद जटिल है, और इसे खुद implement करने में भारी trial and error और बहुत मेहनत लगती है
  • इसके बावजूद, पुराना प्रमाणपत्र छोड़कर पूरी तरह automated तरीके में बदलाव सफलतापूर्वक किया गया
  • अंत में मज़ाक में यह भी कहा गया कि इतनी जटिलता शायद किसी की नौकरी सुरक्षित रखने वाली संरचना तो नहीं है

1 टिप्पणियां

 
GN⁺ 2025-05-24
Hacker News की राय
  • मैं Let’s Encrypt SRE/infra टीम में technical lead हूँ, इसलिए इस तरह की समस्याओं पर बहुत सोचता हूँ
    JSON Web Signature सच में काफ़ी पेचीदा format है, और ACME API भी RESTful होने को लेकर बहुत ज़्यादा गंभीर है
    अगर मैंने इसे खुद design किया होता, तो मैं इसे इस तरह नहीं बनाता
    मुझे लगता है कि इस संरचना के पीछे IETF का IETF standards का ज़्यादा उपयोग करने का इरादा और committee-style design दोनों का बड़ा हाथ था
    अगर JSON, JWS, HTTP के कुछ libraries हों तो चीज़ें काफ़ी बेहतर हो जाती हैं, लेकिन ख़ासकर C में उन libraries का इस्तेमाल भी आसान नहीं है
    RFC की language खुद जटिल है और अक्सर दूसरे documents को refer करती है, इसलिए इसे आसान बनाने के लिए interactive client और documentation पर अलग से काम कर रहा हूँ

    • यह बात समझ नहीं आती कि JSON Web Signature को इतना पेचीदा format क्यों कहा जा रहा है
      मैं ASN.1, Kerberos, PKI जैसी जटिल चीज़ों के साथ बहुत काम करता हूँ, और मुझे JWS उतना कठिन format नहीं लगता
      यहाँ तक कि अगर इसे सीधे code में लिखना पड़े, तब भी यह S/MIME, CMS, Kerberos वगैरह से कहीं आसान है
      JWS आख़िर कहाँ ‘पेचीदा’ है, इस पर और स्पष्टीकरण चाहिए
      अगर समस्या JWT की है, तो असली बात यह है कि HTTP user agent को standard तरीके से JWT कैसे लेना या माँगना चाहिए, यह ठीक से तय नहीं है

    • मैंने किसी को यह कहते देखा कि “3 से ज़्यादा certificates जारी कराने हों तो पैसे देने पड़ते हैं”, लेकिन मैं पिछले 5 साल से इसका इस्तेमाल कर रहा हूँ और मुझे कभी bill नहीं मिला, इसलिए यह ग़लतफ़हमी या misinformation लगती है

  • “e=65537” की जगह “e=AQAB” इस्तेमाल करने की बात करते हुए समझाया गया कि वजह JSON का numbers को ठीक से handle न कर पाना है
    अगर 4723476276172647362476274672164762476438 जैसा बहुत बड़ा number किसी JSON parser को दिया जाए, तो ज़्यादातर JSON parsers चुपचाप उसे 64-bit integer या float में काट देंगे, या ज़्यादा से ज़्यादा error देंगे
    Common Lisp जैसी language इसे ठीक से संभाल सकती है, लेकिन वास्तविक दुनिया में ऐसे environment में development करने वाले बहुत कम हैं
    इसलिए JSON में बड़े numbers को भरोसेमंद तरीके से भेजना हो, तो उन्हें base64 में byte array के रूप में बदलना शायद बेहतर है
    ऊपर से सब ठीक चलता दिखे, फिर भी यही कई security issues की जड़ बन सकता है, इसलिए protocol के सभी numbers को इस तरह handle करना भी उचित लगता है
    हालाँकि इससे JSON की human-friendly readability ख़त्म हो जाती है, और निजी तौर पर मुझे standardized S-Expression कहीं बेहतर विकल्प लगता है
    लेकिन दुनिया ने JSON चुना

    • अगर कोई यह नहीं समझता कि दुनिया ने JSON क्यों चुना, तो मुझे लगता है कि वह जानबूझकर इसे नज़रअंदाज़ कर रहा है
      JSON ज़्यादातर data के लिए इंसानों द्वारा सीधे लिखना/edit करना/पढ़ना बहुत आसान बनाता है
      वहीं Canonical S-Expression में हर element के आगे उसकी length लिखनी पड़ती है, इसलिए हाथ से लिखना बहुत झंझट वाला है
      S-Expression लिखने के लिए हर character गिनना पड़ता है और prefixes भी बदलने पड़ते हैं, जो बेहद परेशान करने वाला है
      उम्मीद के उलट, यही आसान manual editing और modification JSON के टिके रहने की वजह है
      वैसे Ruby JSON parser बड़े numbers को अच्छी तरह handle करता है

    • मैं एक बार C# app में ऐसे bug से जूझ चुका हूँ जहाँ JSON serializer ने BigInt को number के रूप में export किया और JS ने उसे चुपचाप ग़लत समझ लिया
      error की जगह overflow standard behavior है, यह देखकर आज भी हैरानी होती है
      तब से मेरी आदत है कि 32-bit से बड़े numbers को हमेशा string के रूप में handle करूँ

    • {"e":"AQAB"} और {"e":65537} की तुलना में कुछ बात है, लेकिन अगर {"e":"65537"} से तुलना करें तो इसमें भी सभी JSON parsers का परिणाम एक जैसा होगा
      चाहे number हो या string, conversion स्पष्ट है
      बेशक, अगर संख्या इतनी बड़ी हो कि double में न समा सके, तो वह अपने आप में language या parser की समस्या है, representation की नहीं

    • JSON की समस्या format में नहीं, बल्कि इस बात में है कि parser मूल रूप से JS type mapping के लिए बनाए गए थे
      कुछ parsers इसे ठीक से handle कर सकते हैं, लेकिन ऐसा करने पर JSON की portability ख़त्म हो जाती है
      Base64 में बदलने पर भी वही समस्या रहती है (क्योंकि वह standard नहीं है)
      replacer और reviver से custom parsing संभव है, लेकिन हर environment में यह सुविधा guaranteed नहीं है
      आख़िरकार, standard parser से JSON को parse करने की धारणा ही गड़बड़ी की जड़ है
      अगर इसे JSON न कहकर कोई और format कहा जाए, तो शायद ऐसी समस्याएँ कम हों, लेकिन लोग अगर उसे JSON जैसा देखेंगे तो फिर भी सीधे parser में डाल देंगे

    • Go language में json.Number type के ज़रिए numbers को बिना loss के string की तरह decode किया जा सकता है
      मैं अपने लगभग ‘सबसे पसंदीदा’ arbitrary decimal types में से एक का परिचय देता हूँ https://github.com/ncruces/decimal?tab=readme-ov-file#decimal-arithmetic
      आधे-मज़ाक में कहूँ तो, मुझे अब भी ठीक से समझ नहीं आता कि इस मामले में S-Expression बेहतर क्यों होगा
      कुछ LISP implementations में भी arbitrary precision arithmetic का support नहीं होता

  • यह थोड़ा अजीब लगा कि लेखक ACME और कई clients के प्रति इतना आलोचनात्मक क्यों है
    यह सिर्फ usability की समस्या नहीं लगती, इसलिए मैंने अंदाज़ा लगाया कि शायद उसे ACME की अवधारणा या उसके आसपास के tools से ही कुछ चिढ़ है
    हमने भी 2019 से LE के आधार पर कुछ sites पर इसे लागू किया है और इस दौरान कई ACME clients इस्तेमाल किए हैं
    उदाहरण के लिए Crypt-LE हमारे use case के लिए ठीक था, और Sectigo ACME से जुड़ने की कोशिश में le64 काफ़ी नहीं पड़ा, इसलिए certbot, lego, posh-acme वगैरह भी आज़माए
    आख़िर में certbot को GHA environment issue ठीक करके इस्तेमाल किया, और posh-acme भी अच्छा लगा
    दोबारा पढ़ने पर लगा कि लेखक का तीखा tone ACME या clients के बजाय spec की तरफ़ था
    नतीजा यही है कि ACME का idea अच्छा है, लेकिन implementation और वास्तविक उपयोग निराशाजनक है

    • मुझे लगता है कि मेरी सोच लेखक से मिलती-जुलती है
      लेखक की यह बात उद्धृत करता हूँ: “कई मौजूदा clients ख़तरनाक code हैं, और मैं उन्हें अपने server पर root permissions के साथ चलाने लायक भरोसेमंद नहीं मानता”
      security-sensitive कामों में यह सावधानी भरा रवैया पूरी तरह उचित लगता है

    • जिन लोगों को मूल लेख का tone समझना कठिन लगा, उनके लिए संदर्भ देने वाली पुरानी posts के links साझा किए गए

    • बहुत से लोग server पर ऐसी कोई चीज़ चलाना ही पसंद नहीं करते जिसे वे समझते नहीं, और मैं भी इस सोच से सहमत हूँ
      लेकिन security का क्षेत्र cat-and-mouse game जैसा है, इसलिए उसमें लगातार बदलाव होना तय है और आख़िरकार हमें उसके साथ चलना ही पड़ता है
      अच्छी बात यह है कि ACME में अपनी पसंद का client बनाने की आज़ादी है
      certbot का इस्तेमाल करना ज़रूरी नहीं, और यह TPM जैसी कोई ऐसी संरचना भी नहीं है जो आपके संसाधनों को बंद कर दे

  • अगर कोई ACME client को शुरू से implement करना चाहता है, तो अनुभव यह रहा कि RFCs (और संबंधित JOSE आदि documents) को सीधे पढ़ना उम्मीद से आसान है
    किसी ने खुद implementation भी किया और ACME v2 flow को समझाने वाला एक सार-लेख भी साझा किया https://www.arnavion.dev/blog/2019-06-01-how-does-acme-v2-work/
    यह आधिकारिक RFC का विकल्प नहीं है, लेकिन इस लेख को flowchart और method-wise index की तरह उपयोगी reference माना जा सकता है

    • MIT security class के final assignment के रूप में ACME client implement करने का उदाहरण भी साझा किया गया https://css.csail.mit.edu/6.858/2023/labs/lab5.html

    • इस अजीब हक़ीक़त पर व्यंग्य किया गया कि manuals पढ़ने के बजाय अगर आप सारी प्रक्रिया को English में समझाते हुए Hacker News पर post कर दें, तो ज़्यादा internet points मिलते हैं

  • लेखक ने web infrastructure protocols की लगातार बढ़ती complexity की ओर ध्यान दिलाया, इसके लिए आभार व्यक्त किया गया
    कहा गया कि ऐसे standards सिर्फ tools या clients इस्तेमाल करने वाले developers के लिए बोझ नहीं हैं, बल्कि एक तरह की ‘regulatory barrier’ की तरह काम करते हैं, जिससे आख़िर में वही बड़ी स्थापित कंपनियाँ internet संचालन की शर्तें पूरी कर पाती हैं
    सिर्फ ACME अपने आप में असंभव entry barrier नहीं है, लेकिन ऐसी चीज़ें जुड़ते-जुड़ते आख़िरकार एक दीवार बन जाती हैं

    • इस पर आशावादी राय भी आई कि इन protocols के open source implementations मौजूद हैं, और AI की प्रगति के कारण ऐसी बाधाएँ धीरे-धीरे कम होंगी
  • OpenBSD में base OS के साथ आने वाला बहुत सरल और lightweight ACME client मौजूद है
    सुना है कि इसे इसलिए बनाया गया क्योंकि मौजूदा विकल्प बहुत भारी थे और Unix philosophy के खिलाफ़ जाते थे
    अफ़सोस यह लगा कि लेखक ने इस दिशा पर विचार नहीं किया
    शायद थोड़ी मेहनत से इसे दूसरे OSes पर भी port किया जा सकता है

    • इसके उलट, किसी का मानना है कि यह OpenBSD philosophy का एक उदाहरण है जहाँ security इतनी जटिल क्यों है, यह बात समझी ही नहीं गई
      यह client उसी machine पर install करके इस्तेमाल किया जाता है और isolation के ज़रिए components को एक-दूसरे से प्रभावित होने से रोका जाता है
      लेकिन ACME protocol खुद पूरी तरह अलग-अलग संरचना (air-gapping) की अनुमति देता है, यानी webserver, certificate requester और DNS server अलग environments में भी हो सकते हैं
      OpenBSD integrated client का उपयोग न करना अधिक जटिल हो सकता है, लेकिन security design principles के हिसाब से वही बेहतर है
      “बस OpenBSD install कर लो” केवल एक आसान तरीका है

    • uacme (https://github.com/ndilieto/uacme) का भी ज़िक्र हुआ
      यह हल्का C code है, और Let’s Encrypt के Python client से battery issue जैसी परेशानियों के बाद इसे स्थिर विकल्प के रूप में इस्तेमाल किया गया

    • किसी ने साझा किया कि वह खुद OpenBSD ACME client इस्तेमाल कर रहा है और यह बहुत अच्छी तरह काम करता है

  • “4096-bit RSA private key बनाओ” जैसी सिफ़ारिश असल में visitors के लिए speed कम करती है और व्यावहारिक security 2048-bit के आसपास ही रहती है
    इसलिए 2048-bit leaf certificate का उपयोग बेहतर बताया गया

    • सवाल पूछा गया कि क्या 4096-bit passive capture / future decryption के ख़िलाफ़ ज़्यादा मज़बूत नहीं होगा
      यह भी पूछा गया कि intermediate certificate security पर asynchronous attacks का असर पड़ता है या नहीं

    • किसी web host ने सिर्फ RSA keys का support दिया, इसलिए जानबूझकर 4096-bit RSA इस्तेमाल किया गया ताकि वे जल्दी EC keys support करें

  • इस तरह के काम खुद करने से skill ज़रूर बढ़ती है, लेकिन लेखक की writing का tone protocol या Let’s Encrypt setup पर चिढ़ा हुआ लगता है
    lightweight ACME libraries (https://github.com/jmccl/acme-lw आदि) से भी काफ़ी automation हो सकता है, तो फिर इसे इतना मुश्किल क्यों बनाया जा रहा है, यह सवाल उठाया गया

    • साफ़ कहा गया कि SSL सचमुच ‘गरम और जमे हुए अराजकता का ढेर’ है
      flat/bitfield जैसी समस्याएँ ASN.1/X.509 की ऐतिहासिक विरासत हैं, जहाँ गणितीय जटिलता बहुत अधिक है, और सारी libraries व software अब भी 80s की तकनीकी सीमाओं से बँधे हुए हैं
      Let’s Encrypt के आगमन या HTTP/2 के समय इस अराजकता को साफ़ करने का शायद आख़िरी मौका था, लेकिन व्यवहार में ACME CA को shell scripts, OpenSSL और थोड़ी शराब के सहारे भी चला लिया जाता है, और पुराने software के साथ compatibility की मजबूरी के कारण बड़ा उछाल नहीं आ सका
  • HTTPS की ओर बढ़ते दबाव का अनुभव साझा किया गया
    उदाहरण के लिए WhatsApp में अब HTTP links खोले नहीं जा सकते

    • proxy और caching के इस्तेमाल से traffic का बोझ कम किया जा सकता है, और छोटे servers के लिए यह अच्छा तरीका है

    • इस बात पर ज़ोर दिया गया कि ACME कितना भी जटिल हो, TLS support न होने से तो कहीं बेहतर है

  • “RSA key, SHA256 digest, RSA signature, असल में base64 नहीं बल्कि base64, string concatenation, JSON के भीतर JSON, 301 redirect की जगह identifier की तरह Location header का इस्तेमाल, एक header value के लिए HEAD request, हर request के लिए nonce के उद्देश्य से अलग request की ज़रूरत—ऐसे कई तत्व एक के ऊपर एक चढ़े हुए हैं”
    “और अभी भी certificate order बनाना, authorization और challenge संभालना, key thumbprint, TXT record बनाना जैसे और भी जटिल चरण बाकी हैं”
    यह अविश्वसनीय स्तर की complexity है, और इस तरह का सारांश साझा करने के लिए धन्यवाद दिया गया