NIST कर्व सीड्स हल: ECDSA की उत्पत्ति के बारे में 5 मिथक
NIST ECDSA कर्व सीड्स दरअसल lrand48(time) से बने थे। नो-अप-माई-स्लीव नंबर, बैकडोर और LLM क्रिप्टो ऑडिटिंग के बारे में पाँच मिथक।

बीस साल से ज़्यादा समय तक, NIST ECDSA कर्व सीड्स एप्लाइड क्रिप्टोग्राफ़ी के सबसे करीबी 'अनसुलझे कोल्ड केस' जैसे थे। पाँच दिखने में रैंडम 160-बिट वैल्यूज़, जिन्हें NSA ने बिना किसी स्पष्टीकरण के NIST को सौंपा था, और जो आपके TLS कनेक्शन से लेकर Bitcoin ट्रांज़ैक्शन तक हर चीज़ के सिग्नेचर को सपोर्ट करती हैं। इस हफ़्ते केस बंद हो गया, और जवाब लगभग शर्मिंदा करने वाला है: ये सीड्स C लाइब्रेरी के lrand48() जनरेटर का आउटपुट थे, जिन्हें 1997 और 1998 के Unix टाइमस्टैम्प से सीड किया गया था। बस इतना ही। किसी गुप्त पासफ़्रेज़ का हैश नहीं, कोई एक्ज़ॉटिक मशीनरी नहीं — srand48(time(NULL)), वही पैटर्न जिसे हर सिक्योरिटी कोर्स आपको कभी न इस्तेमाल करने को कहता है।
यह खोज एक Anthropic रिसर्च मॉडल से हुई, जिसे एक जिज्ञासु कर्मचारी ने इस समस्या पर लगाया था। मॉडल ने प्रकाशित कॉन्स्टेंट्स में 1990 के दशक के linear congruential generator का सांख्यिकीय सिग्नेचर पहचाना और स्टेट को उल्टा चलाकर कैलेंडर तारीखों तक पहुँच गया। मैंने क्रिप्टोग्राफ़िक सिस्टम ऑडिट करने में इतने साल बिताए हैं कि जानता हूँ यह क्यों मायने रखता है — इसलिए नहीं कि कर्व टूटे हुए हैं (वे नहीं हैं), बल्कि इसलिए कि इसने हमारी इंडस्ट्री की कई आत्मविश्वास भरी मान्यताओं को ध्वस्त कर दिया है। आइए मिथकों को एक-एक करके देखें।
मिथक 1: बिना समझाए गए कॉन्स्टेंट्स का मतलब छिपा हुआ बैकडोर है
यह शक कभी बेतुका नहीं था। जब NIST ने 2000 में FIPS 186-2 कर्व प्रकाशित किए, तो हर कर्व के साथ एक सीड आया था जिसका हैश कर्व के गुणांक b को तय करता है। NIST ने कहा कि सीड्स गारंटी देते हैं कि कर्व ‘वेरिफ़ायबली रैंडम’ हैं — लेकिन यह नहीं बता पाया, या बताना नहीं चाहा, कि सीड्स खुद कैसे बने। Koblitz और Menezes ने इस विवाद पर पूरा पेपर लिखा, जिसका शीर्षक था ‘A Riddle Wrapped in an Enigma’। समुदाय का सबसे अच्छा सुराग NSA के Jerry Solinas थे, जिन्होंने 2015 में याद किया कि इनपुट किसी मज़ाकिया वाक्य का हैश था, कुछ ऐसा जैसे ‘Give Bob and Jerry a raise’। 2023 में उनका निधन हो गया, और विवरण कभी किसी को नहीं मिले।
साज़िश-प्रेमी लोगों के लिए यहाँ एक असहज सच है, और कुछ हद तक मैं खुद भी ऐसा सोचता था: 'बिना समझाए गए' का आम तौर पर मतलब होता है 'बिना दस्तावेज़ीकरण', न कि 'दुर्भावनापूर्ण'। असली जनरेशन प्रक्रिया यह थी कि एक डेवलपर ने एक छोटा C प्रोग्राम चलाया, डिफ़ॉल्ट PRNG को दीवार घड़ी से सीड होने दिया, और पहला ऐसा कैंडिडेट ले लिया जो इस्तेमाल लायक कर्व दे। P-256 का प्रकाशित सीड कैंडिडेट नंबर 1,842 था, जो 16 अगस्त 1997 की सुबह 1:52 बजे शुरू हुई एक रन से आया था। यह किसी एजेंसी का नंबर-थ्योरी ट्रैपडोर लगाने का तरीका नहीं है। यह एक इंजीनियर है जो रात के एक बजे एक लूप तब तक चला रहा है जब तक कुछ वैध न छप जाए।
मैंने इस पैटर्न को इंसिडेंट रिव्यू में गिनती से ज़्यादा बार देखा है। एक रहस्यमयी कॉन्फ़िग वैल्यू, एक अनडॉक्युमेंटेड मैजिक कॉन्स्टेंट, एक डिप्लॉयमेंट स्टेप जिसे कोई समझा नहीं सकता — और पोस्टमॉर्टम में पता चलता है कि यह एक थके हुए इंजीनियर का उस समय के हिसाब से समझदारी भरा शॉर्टकट था, जो कभी लिखा नहीं गया। यहाँ NSA का असली पाप कर्व में बैकडोर लगाना नहीं था। पाप यह था कि उसने क्रिप्टोग्राफ़िक कॉन्स्टेंट्स पूरी दुनिया को बिना README के भेज दिए।
मिथक 2: जनरेशन का तरीका साबित करता है कि चयन ईमानदार था
अब ओवरकरेक्शन। इस हफ़्ते की ज़्यादातर टिप्पणियाँ ‘ये तो बस टाइमस्टैम्प हैं’ को पूरी तरह से बरी होने का प्रमाण मान रही हैं। ऐसा नहीं है, और इस काम से जुड़े शोधकर्ता खुद इस बात को सावधानी से कहते हैं। यह जानना कि कैंडिडेट कैसे बने, यह नहीं बताता कि अंतिम कर्व कैसे चुने गए — और यह चयन मई 1997 से अप्रैल 1998 तक महीनों में हुआ।
सबूत दोनों तरफ़ जाते हैं। P-256 की रन में, कैंडिडेट 876 ने भी उसी आकार का प्राइम-ऑर्डर कर्व दिया था, उन्हीं पैरामीटर कन्वेंशन्स से बना — और उसे छोड़ दिया गया। प्रकाशित कर्व कैंडिडेट 1,842 था। P-224 की रन ने तीन व्यवहार्य कर्व छोड़े; ANSI X9.62 की रनों ने सात और छोड़े। छोड़े गए कैंडिडेट्स का पूरा इतिहास हम नहीं देख सकते, सिर्फ़ वही जो रिकॉर्ड की गई रनों से पहुँचे जा सकते हैं। अगर किसी को कोई खास दुर्लभ गुण वाला कर्व चाहिए था, तो सिद्धांत रूप में वह टाइमस्टैम्प्स में तब तक खोज सकता था जब तक कोई मिल न जाए, और फिर टाइमस्टैम्प के बारे में चुप रह सकता था। ‘करना और कुछ न कहना’ हमेशा एक विकल्प था।
वीक कर्व रिसर्च पर सालों से नज़र रखने के बाद मेरी राय यह है: बैकडोर वाली परिकल्पना बुरी तरह घायल है, पर औपचारिक रूप से मरी नहीं है। छोड़े गए कैंडिडेट्स इतने कम हैं कि चेरी-पिकिंग का मतलब होगा कि कमज़ोर कर्व आम और आसानी से मिलने वाले हैं — जबकि दो दशकों की सार्वजनिक क्रिप्टएनालिसिस कहती है कि ऐसा नहीं है। इन कर्व्स को रैंडम कर्व्स से अलग करने वाला कोई डिस्टिंगुइशर कभी प्रकाशित नहीं हुआ। लेकिन ‘ज्ञात कमज़ोरी नहीं है’ और ‘साबित रूप से कोई कमज़ोरी नहीं है’ अलग बयान हैं, और ईमानदार स्थिति पहली वाली है। यह ठीक वही विशिष्टता-कार्यान्वयन अंतर है जो मानक स्तर पर खेला जा रहा है: स्पेक ने कहा ‘वेरिफ़ायबली रैंडम’, और इम्प्लीमेंटेशन था ‘जो भी घड़ी ने बताया’।
सीड्स वैसे ही बने जैसे कोई ग्रेड स्टूडेंट बनाता: एक स्टॉक PRNG और सिस्टम की घड़ी। घोटाला कभी गणित का नहीं था। वह गायब दस्तावेज़ीकरण का था।
मिथक 3: पुराने कमज़ोर PRNG अगर सिर्फ़ एक बार इस्तेमाल करो तो हानिरहित हैं
यह वह मिथक है जो हर उस इंजीनियर को चौंका देना चाहिए जिसने कभी srand(time(NULL)) टाइप किया हो। पच्चीस साल का पूरा रहस्य-आवरण lrand48() की एक डिज़ाइन विशेषता की वजह से था: यह अपनी संरचना लीक करता है। यह 48-बिट स्टेट के सिर्फ़ ऊपरी 31 बिट लौटाता है, इसलिए इसके आउटपुट वर्ड्स में हमेशा टॉप बिट ज़ीरो होता है। 32-बिट वर्ड्स के रूप में देखें तो दस बाइनरी-कर्व सीड्स में से चार में बीस लगातार वर्ड्स तक टॉप बिट्स पूरी तरह ज़ीरो दिखते हैं — यूनिफ़ॉर्म डिस्ट्रीब्यूशन में इसकी संभावना लगभग 58,000 में एक है। जो कोई इस पर ध्यान देता, उसे यह पैटर्न नंगी आँखों से दिख जाता।
इसके बाद हमला बेशर्मी की हद तक सस्ता है। बाइनरी-कर्व स्टेट निकालने के लिए आप पहला आउटपुट वर्ड लेते हैं, छिपे हुए 2^17 निचले बिट्स को ब्रूट-फ़ोर्स करते हैं, और देखते हैं कि अगले चार वर्ड उसी का अनुसरण करते हैं या नहीं। इसमें कुछ मिलीसेकंड की कंप्यूट लगती है। प्राइम कर्व्स के लिए सीड्स ने हर आउटपुट में कम बिट्स रखे थे, इसलिए स्टेट निकालने के लिए क्लासिक ट्रंकेटेड-LCG अटैक चाहिए: इसे लैटिस समस्या मानकर LLL basis reduction से हमला करना। शाब्दिक रूप से किताबी सामग्री। एक बार स्टेट मिल जाए, तो LCG उतनी ही आसानी से उल्टा चलता है जितना सीधा, तो आप उसे तब तक पीछे ले जाते हैं जब तक वह srand48 इनिशियलाइज़ेशन का रूप न दिखाए — यानी निचले बिट्स 0x330E के बराबर हों — और वह टाइमस्टैम्प पढ़ लेते हैं जिससे वह सीड हुआ था।
# The whole mystery, reproduced
from datetime import datetime, timezone
def unix(when):
return int(datetime.fromisoformat(when).replace(tzinfo=timezone.utc).timestamp())
def candidate(t, n, per, shift, width):
x, out = (t << 16) | 0x330E, "" # state set by srand48(t)
for i in range(per * n):
x = (0x5DEECE66D * x + 0xB) % 2**48 # one lrand48 step
if i >= per * (n - 1):
out += "%0*X" % (width, x >> shift)
return out
# P-256: run started 1997-08-16 01:52:34 UTC, candidate 1842
print(candidate(unix("1997-08-16 01:52:34"), 1842, 20, 40, 2))
# -> C49D360886E704936A6678E1139D26B7819F7E90 (the published NIST seed)
यह सबक स्टैंडर्ड बॉडीज़ से आगे तक जाता है। कोई भी ‘रैंडम-दिखने वाली’ वैल्यू जो आप बनाते हैं — सेशन टोकन, रिक्वेस्ट ID, salt, फ़ाइलनाम — उस जनरेटर का फ़िंगरप्रिंट लिए होती है जिसने उसे बनाया। अगर वह जनरेटर linear congruential engine या Mersenne Twister है, तो कुछ आउटपुट से ही इंटरनल स्टेट दोबारा बन जाता है, और उससे पहले और बाद में बनी हर चीज़ अनुमानित हो जाती है। पच्चीस साल पहले एक बार का इस्तेमाल, एक ऐसी फ़ाइल में जो शोर जैसी दिखने के लिए बनी थी, पूरी तरह उलट दिया गया। जब मैं ऐसा कोड रिव्यू करता हूँ जो किसी हमलावर द्वारा देखे जा सकने वाली किसी भी चीज़ के लिए गैर-क्रिप्टोग्राफ़िक RNG इस्तेमाल करता है, तो अब से यही वॉर स्टोरी मैं सबसे पहले उद्धृत करता हूँ।

मिथक 4: नथिंग-अप-माई-स्लीव नंबर्स ने कभी असली सुरक्षा नहीं दी
‘नथिंग-अप-माई-स्लीव’ का विचार — ऐसे कॉन्स्टेंट्स निकालना जो स्पष्ट रूप से निर्दोष चीज़ों से आएँ, जैसे pi के अंक — डिज़ाइनर की स्वतंत्रता की सीमा तय करने के लिए है। अगर मैं आपको दिखा सकूँ कि मेरा कॉन्स्टेंट एक सार्वजनिक, कठोर प्रक्रिया से निकला है, तो मेरे पास ट्रैपडोर छिपाने की जगह नहीं थी। लेकिन NIST के सीड्स प्रक्रियात्मक रूप से इस परीक्षा में फेल हुए: प्रक्रिया गुप्त थी, इसलिए स्वतंत्रता की सीमा अज्ञात थी। पर यह प्रकरण असल में जो उजागर करता है वह यह है — स्लीव टेस्ट उतना मज़बूत नहीं है जितना हम दिखावा करते थे, भले ही वह काम करता हो।
सोचिए कि ‘टाइमस्टैम्प से निकला, सत्यापित रूप से रैंडम’ होने से वास्तव में क्या मिलता है। एक संभावित विंडो के लिए टाइमस्टैम्प लगभग 31 बिट एंट्रॉपी देता है। कोई भी — मूल लेखक सहित — लाखों टाइमस्टैम्प्स में से ग्राइंड कर सकता है, लाखों कैंडिडेट कर्व बना सकता है, और सिर्फ़ वही प्रकाशित कर सकता है जो उसे चाहिए, उसके निर्दोष दिखने वाले सीड के साथ। अगर छिपी कमज़ोरी वाले कर्व एक मिलियन में एक की दर से मौजूद हों, तो टाइमस्टैम्प-ग्राइंडिंग एक दोपहर में एक ढूँढ लेगी। सीड बताता है कि नंबर कहाँ से आया, पर यह लगभग नहीं बताता कि वही एक क्यों चुना गया। यही बात पासफ़्रेज़ के हैश वाली स्कीम पर भी लागू होती है, और इसीलिए Solinas के मज़ाकिया वाक्य की अफ़वाह भी कभी पूरी तरह आश्वस्त नहीं करती थी।
आज का मज़बूत तरीका है रिजिड कर्व कंस्ट्रक्शन: सार्वजनिक सुरक्षा मानदंडों की सूची को संतुष्ट करने वाला सबसे छोटा गुणांक चुनना, और खोज शुरू होने से पहले चयन नियम तय कर देना। Curve25519 के पीछे यही दर्शन है, और Dan Bernstein के रिजिडिटी तर्कों ने बदला कि समुदाय कर्व्स का मूल्यांकन कैसे करता है। दुर्भावनापूर्ण कॉन्स्टेंट्स के खिलाफ असली सुरक्षा कभी कोई प्यारी व्युत्पत्ति वाली कहानी नहीं थी। यह खोज-स्पेस को कम करना, मानदंड पहले से प्रकाशित करना, और गणित पर इतनी स्वतंत्र नज़रें रखना है कि कोई छिपा गुण छिपा न रह सके। कॉन्स्टेंट्स का ऑडिट करने का मतलब है उस प्रक्रिया का ऑडिट करना जिसने उन्हें छाना — इसीलिए यहाँ के अनुत्तरित सवाल (छोड़े गए कैंडिडेट्स, P-256 और उसके साथियों के अस्पष्ट बेस पॉइंट्स, अब भी अनपहचाने B-163 सीड) उत्सव के शोर में दबाए जाने के बजाय रिकॉर्ड पर खुले रहने चाहिए।
मिथक 5: LLM बस दोहराते हैं — वे मौलिक क्रिप्टएनालिसिस नहीं कर सकते
यह मिथक सबसे ज़्यादा चुभता है, क्योंकि मैं इसके एक रूप पर खुद विश्वास करता था। यह खुली समस्या पच्चीस साल तक $36,864 के सार्वजनिक बाउंटी और कुशल शौकीनों की गंभीर कोशिशों के बावजूद अनसुलझी रही। Anthropic के कुछ शोधकर्ताओं ने इसे खुद ‘मज़ाकिया वाक्य के हैश’ वाले सुराग पर चलकर खोजा था और खाली हाथ लौटे थे। फिर एक आंतरिक रिसर्च मॉडल से, बिना अफ़वाह बताए, पूछा गया, और उसने आधे घंटे से कम में अलग कोण आज़माया: हैश का इनपुट अनुमान लगाने के बजाय उसने पूछा कि सीड्स किस सॉफ़्टवेयर ने बनाए होंगे, 1990 के दशक की C लाइब्रेरी PRNG की परिकल्पना की, एक स्कैनर लिखा जो हर सीड पर फिसलते हुए 34 जनरेटर और आउटपुट स्लाइस के संयोजनों की जाँच करता था, ज़ीरो-टॉप-बिट पैटर्न पकड़ा, ट्रंकेटेड आउटपुट पर लैटिस अटैक चलाया, और स्टेट्स को कैलेंडर तारीखों तक वापस ले गया।
इस वर्कफ़्लो को देखिए। यह रिकॉल नहीं था — किसी ट्रेनिंग दस्तावेज़ में उत्तर था ही नहीं, क्योंकि उत्तर कहीं मौजूद नहीं था। यह हाइपोथेसिस जनरेशन, टूल इस्तेमाल और सत्यापन का मेल है, जो असल में क्रिप्टएनालिसिस का काम है। मॉडल ने रन के बीच अपनी ही समझदारी भी जाँची: क्या यह कोई सिम्युलेटेड टेस्ट एनवायरनमेंट है, क्या इतनी स्पष्ट चीज़ 25 साल तक सचमुच अनदेखी रह सकती है, क्या 32-बिट सीड से मिला 160-बिट मैच संयोग को खारिज करता है? यही आत्म-संदेह मैं किसी इंसानी विश्लेषक से चाहता हूँ, और ईमानदारी से कहूँ तो कुछ इंसानी विश्लेषक इसे छोड़ देते हैं। हम इस साइट पर कुछ समय से LLM वास्तव में क्या करते हैं, इसके इर्द-गिर्द मिथकों की जाँच कर रहे हैं, और यह एक साफ़ डेटा पॉइंट है: LLM अब बेंचमार्क ही नहीं, वास्तविक दुनिया के आर्टिफ़ैक्ट्स पर बहु-चरणीय फ़ॉरेंसिक तर्क चला सकते हैं।
प्रैक्टिशनर्स की ओर से एक उचित प्रति-दलील प्रोवेनेंस के बारे में है। मॉडल ने LCG स्टेट रिकवरी या LLL का आविष्कार नहीं किया — वह दशकों के प्रकाशित क्रिप्टएनालिसिस पर खड़ा है, जो नामी और बेनाम शोधकर्ताओं ने लिखा, और वह आपको नहीं बता सकता कि उसके तरीके को किसके पेपरों ने आकार दिया। यह मुझे उतना परेशान नहीं करता जितना कुछ लोगों को करता है। स्कैनर, सत्यापन कोड और रीप्रोडक्शन स्क्रिप्ट सार्वजनिक हैं; टीम के इंसानों ने सवाल तय किया और नतीजे को मान्य किया। काम के बँटवारे को ईमानदारी से श्रेय दीजिए: मशीन ने अथक हाइपोथेसिस खोज दी, इंसानों ने विवेक और जवाबदेही दी। $36,864 का बाउंटी Internet Security Research Group को जाना इस मामले को निपटाने का एक शानदार तरीका था।

इसका सिक्योरिटी ऑडिट पर असर
तो एक कार्यरत इंजीनियर के लिए इसका क्या मतलब है? ऑडिट को लेकर मेरे तरीके में कुछ ठोस बदलाव आएँगे। पहला, किसी प्रोटोकॉल या कोडबेस के हर मैजिक कॉन्स्टेंट को प्रकृति का तथ्य नहीं, बल्कि एक फ़ॉरेंसिक आर्टिफ़ैक्ट मानिए। पूछिए कि उसे कौन सा जनरेटर बना सकता था, और ‘यह रैंडम है’ को जवाब मानने से पहले संरचनात्मक फ़िंगरप्रिंट जाँचिए — पक्षपाती टॉप बिट्स, LCG-सहसंबद्ध लगातार वर्ड्स, टाइमस्टैम्प-जैसे विश्वसनीय स्टेट रिकवरी। इसके लिए टूलिंग अब बहुत आसानी से उपलब्ध है।
दूसरा, अगर आप कॉन्स्टेंट्स प्रकाशित करते हैं, तो जनरेटर भी प्रकाशित कीजिए। सोर्स कोड, सटीक इनपुट, सटीक एनवायरनमेंट। बिना दोहराने योग्य विधि के ‘सत्यापित रूप से रैंडम’ कहना आपको पच्चीस साल का शक और अपनी विरासत पर एक बाउंटी दिला सकता है। तीसरा, P-256 का इस्तेमाल जारी रखिए — यह खोज कर्व्स पर भरोसा घटाती नहीं, बढ़ाती है, और इलिप्टिक कर्व्स के लिए वास्तविक थ्रेट मॉडल असल में क्वांटम हार्डवेयर है, 1997 की एक वर्कस्टेशन की घड़ी नहीं। पर खुले सवालों को ईमानदारी से पढ़िए: अस्पष्ट बेस पॉइंट्स और छोड़े गए कैंडिडेट्स ढीले सिरे हैं, और परिपक्व सिक्योरिटी काम का मतलब है उन्हें बही-खाते में खुला रखना।
सबसे गहरा सबक संस्थागत स्मृति के बारे में है। Jerry Solinas को मज़ाक याद था जो गलत निकला। उनके अपने शब्दों में, पुराने रिकॉर्ड शायद कॉवनेंट के आर्क के पास किसी हार्ड ड्राइव पर पड़े थे। आज हम सच इसलिए जानते हैं क्योंकि आउटपुट में खुद इतनी संरचना बची थी कि वह कबूल कर सके। आपके सिस्टम अभी, हर ID, हर टोकन और हर कॉन्स्टेंट में, अपना कबूलनामा लिख रहे हैं। सुनिश्चित कीजिए कि वे कुछ ऐसा कबूल करें जिस पर आपको गर्व हो।


