- Go 1.22 ने
math/randऔरmath/rand/v2के default random sources को cryptographically strong generator में बदल दिया है, जिससे जहांcrypto/randइस्तेमाल होना चाहिए था वहां गलती से दूसरा विकल्प इस्तेमाल करने पर होने वाला नुकसान काफी कम हो जाता है - पुराना Go 1 generator 607
uint64states का उपयोग करने वाला linear feedback shift register है, इसलिए केवल 607 outputs देखकर भी past और future values को recover किया जा सकता है math/rand/v2का PCG-DXSM statistical random quality और state size को बेहतर बनाता है, लेकिन secret values के लिए जरूरी unpredictability की guarantee नहीं देता- नया ChaCha8Rand 32-byte seed, हर 16 blocks पर rekeying, और प्रति core 300-byte state का उपयोग करता है, और इसे
math/rand/v2,math/randके कुछ हिस्सों और map hash seeds में लागू किया गया है - performance cost सीमित है: ChaCha8Rand Go 1 generator से धीमा है, लेकिन अधिकतम 2x के भीतर रहता है, और सामान्य servers में अंतर 3ns से ज्यादा नहीं होता, इसलिए अधिकांश programs में security gain ज्यादा बड़ा है
Go 1.22 ने random defaults कैसे बदले
- Go 1.22 ने
math/randऔरmath/rand/v2में default रूप से cryptographically strong pseudorandom number generator इस्तेमाल करने के लिए defaults बदल दिए हैं - इसका उद्देश्य तब होने वाले नुकसान को कम करना है जब developers गलती से उन जगहों पर
math/randइस्तेमाल कर लें जहांcrypto/randकी जरूरत होती है - Go की random API परंपरागत रूप से दो categories में बंटी रही है
math/rand: simulations, sampling, numerical analysis, non-cryptographic randomized algorithms, fuzzing, shuffling, exponential backoff आदि के लिए इस्तेमाल होने वाले statistical random numberscrypto/rand: keys और tokens जैसी चीजों के लिए, जहां unpredictability जरूरी होती है, इस्तेमाल होने वाले cryptographic random numbers
statistical random numbers पर्याप्त क्यों नहीं हैं
- अगर statistical random number generators basic statistical tests pass कर लें, तो वे कई non-cryptographic use cases के लिए पर्याप्त हो सकते हैं
- लेकिन कई मामलों में algorithm जानने वाला observer पर्याप्त outputs देखकर आगे की sequence predict कर सकता है
- Unix V3 के
srandऔरrandशुरुआती रूप थे जिन्होंने बाद में C और कई languages की random APIs को प्रभावित किया- एक single integer seed से state set की जाती थी
- linear congruential generator (LCG) तरीके से next value calculate की जाती थी
- internal state सरल होने के कारण सिर्फ एक output से भी future values आसानी से calculate की जा सकती थीं
- LCG में constants ऐसे चुने जा सकते हैं कि possible output values repeat होने से पहले एक-एक बार निकलें, लेकिन इसकी कमजोरी यह है कि low bits छोटे cycle में repeat होते हैं
Go 1 generator की structure और vulnerability
- Go 1 का
math/randgenerator linear feedback shift register family का है - internal state 607
uint64वालीvecslice हैvec[606]“tap” हैvec[334]“feed” है- next value बनाते समय tap और feed को जोड़कर
xबनाया जाता है,xको feed position में store किया जाता है और फिर return किया जाता है
- actual implementation पूरी slice को move नहीं करता, बल्कि cost कम करने के लिए सिर्फ tap और feed positions को पीछे move करता है
- next value generate करने के लिए दो subtractions, दो conditional additions, दो loads, एक addition और एक store की जरूरत होती है
- return value internal state vector का एक element होता है, इसलिए 607 outputs पढ़ने पर पूरी state expose हो जाती है
- वही
vecभरकर algorithm चलाने पर future values predict की जा सकती हैं - algorithm उल्टा चलाने पर past values भी recover की जा सकती हैं
- वही
- Go 1 generator security purpose के लिए नहीं है, और generated numbers की quality भी initial
vecsetup पर निर्भर करती है
PCG ने क्या बेहतर किया और क्या limitations बचीं
math/rand/v2ने एक ज्यादा modern statistical random number generator के रूप में Melissa O’Neill का PCG अपनाया- Go का PCG 128-bit LCG पर आधारित है, और
scramblefunction से 128-bit state को 64-bit output में घटाता है - proposal discussion के दौरान Go ने O’Neill के proposal के आधार पर multiplication-based
scrambleइस्तेमाल किया- इस form को PCG-DXSM कहा जाता है
- Numpy भी इसी PCG form का उपयोग करता है
- PCG की state Go 1 generator की तुलना में बहुत छोटी है
- Go 1 generator: 607
uint64 - PCG: दो
uint64
- Go 1 generator: 607
- PCG initial state value के प्रति कम sensitive है और कई statistical tests pass करता है, लेकिन unpredictability की guarantee नहीं देता
- PCG-XSL-RR reversible है
- PCG-DXSM भी reversible हो तो यह आश्चर्यजनक नहीं माना जाएगा
- secret values generate करने के लिए PCG नहीं, बल्कि किसी दूसरे generator की जरूरत होती है
cryptographic random numbers और operating system की भूमिका
- cryptographic random numbers उन observers के लिए भी practically unpredictable होने चाहिए जो generation method जानते हों और बहुत सारे past output values देख चुके हों
- cryptographic protocols, secret keys, modern commerce, online privacy आदि cryptographic random numbers पर निर्भर करते हैं
- actual random supply operating system संभालता है
- mouse, keyboard, disk, network timing जैसे physical devices से randomness collect की जाती है
- हाल में CPU द्वारा सीधे measured electrical noise का भी इस्तेमाल होता है
- जब operating system पर्याप्त randomness, जैसे कम से कम 256 bits, collect कर लेता है, तो वह hash या encryption algorithm से लंबी random sequence बनाता है
- पहले
/dev/randomजैसी device files मुख्य रूप से इस्तेमाल होती थीं, लेकिन आज operating systems direct system calls provide करते हैं - Go का
crypto/randoperating system-specific differences को hide करता है और समान interfacerand.Readprovide करता है
ChaCha8Rand design
- Go 1.22 का नया generator ChaCha8Rand, Daniel J. Bernstein के ChaCha stream cipher का हल्का modified form है
- ChaCha का ChaCha20 form, जो TLS और SSH में भी इस्तेमाल होता है, व्यापक रूप से इस्तेमाल किया जाता है
- Jean-Philippe Aumasson की Too Much Crypto 8-round form ChaCha8 को भी सुरक्षित मानती है, और ChaCha8 लगभग 2.5 गुना तेज है
- ChaCha8Rand, ChaCha8 को
rand.Sourceके रूप में इस्तेमाल करने के लिए generated blocks को input के साथ XOR नहीं करता, बल्कि सीधे random stream के रूप में उपयोग करता है- यह सभी zero data को encrypt या decrypt करने जैसा है
ChaCha8Rand में बदलाव
- ChaCha8Rand 32-byte seed को ChaCha8 key के रूप में इस्तेमाल करता है
- ChaCha8 64-byte blocks generate करता है, और calculation blocks को 16
uint32के रूप में treat करती है - general implementation SIMD instructions से 4 blocks एक साथ calculate कर सकती है, लेकिन XOR input में इस्तेमाल करने के लिए interleaved blocks को फिर से खोलना पड़ता है
- ChaCha8Rand इसी interleaved block को random stream के रूप में define करता है, जिससे unshuffle cost खत्म हो जाती है
- ChaCha8 के block finalization stage में हर
uint32में specific value जोड़ी जाती है- आधा key material है और आधा known constants हैं
- ChaCha8Rand known constants को दोबारा नहीं जोड़ता, जिससे final additions का आधा हिस्सा हट जाता है
- हर 16वें generated block पर आखिरी 32 bytes को अगले 16 blocks की key के रूप में इस्तेमाल किया जाता है
- यह rekeying एक तरह की forward security provide करती है
- generator की पूरी memory state expose हो जाए, तब भी केवल last rekeying के बाद की values recover की जा सकती हैं, past values तक पहुंच नहीं मिलती
- Go ने ChaCha8Rand C2SP specification और test cases publish किए हैं, ताकि same seed के लिए दूसरे implementations भी Go implementation जैसी repeatability share कर सकें
standard library में कहां लागू हुआ
- Go runtime operating system द्वारा supplied cryptographic random numbers से seeded per-core ChaCha8Rand state maintain करता है
- हर core के लिए state size 300 bytes है
- 16-core system में यह single shared Go 1 generator state 4,872 bytes के आसपास ही है
- per-core state के कारण lock contention के बिना तेजी से random numbers बनाए जा सकते हैं
math/rand/v2के package functions हमेशा ChaCha8Rand का उपयोग करते हैं- उदाहरण:
rand.N,rand.Float64
- उदाहरण:
math/randके package functions, अगरrand.Seedcall नहीं किया गया है, तो ChaCha8Rand का उपयोग करते हैं- उदाहरण:
rand.Intn,rand.Float64 rand.Seedcall होने पर compatibility के लिए Go 1 generator पर वापस जाना पड़ता है
- उदाहरण:
- runtime नए map के hash seed को पहले के wyrand-based generator की जगह ChaCha8Rand से चुनता है
- अगर attacker map implementation का specific hash function जानता है, तो वह input तैयार करके map को quadratic-time behavior की ओर धकेल सकता है
- global seed की जगह per-map seed इस्तेमाल करने से दूसरी degenerate behaviors भी टाली जा सकती हैं
- map seed के लिए cryptographic random numbers अनिवार्य हैं या नहीं, यह स्पष्ट नहीं है, लेकिन यह बदलाव सरल और सावधानीपूर्ण choice था
- अलग ChaCha8Rand instance की जरूरत वाले code सीधे
rand.ChaCha8बना सकते हैं
security mistakes का नुकसान कम करना
- Go का लक्ष्य security problems पैदा करने वाली आम गलतियों को घटाकर या हटाकर safe by default code लिखने में मदद करना है
- Go 1.20 में
math/randकाReaddeprecated होने पर कुछ developers को पता चला कि वे key material generation जैसी जगहों पर भीcrypto/randकी जरूरत होने के बावजूदmath/randइस्तेमाल कर रहे थे - Go 1.20 में ऐसी गलती serious security issue थी
- key कहां इस्तेमाल हुई
- key कैसे expose हुई
- क्या दूसरे random outputs ने attacker को key derive करने का clue दिया, इसकी जांच करनी पड़ती थी
- Go 1.22 में वही गलती अब भी गलती है, लेकिन security disaster बनने की संभावना कम हो जाती है
- फिर भी secret values के लिए
crypto/randइस्तेमाल करना बेहतर है- operating system kernel random values को बेहतर protect कर सकता है
- kernel generator में नई entropy लगातार add करता है
- kernel implementation की ज्यादा review हुई है
ऐसे cases जो cryptographic नहीं लगते
- random UUID generation में UUID secret value नहीं होता, इसलिए
math/randपर्याप्त लग सकता है - लेकिन अगर
math/randको current time से seed किया जाए, तो अलग-अलग computers एक ही समय पर चलने पर same values बना सकते हैं- जिन systems में current time केवल millisecond precision देता है, वहां यह संभावना और बढ़ जाती है
- Go 1.20 की OS entropy-based automatic seeding के बावजूद, Go 1 generator का seed सिर्फ 63-bit integer है
- startup पर UUID बनाने वाले program का possible first UUID 2⁶³ तक सीमित होता है
- लगभग 2³¹ UUIDs के बाद collision की संभावना बनती है
- Go 1.22 का ChaCha8Rand 256-bit entropy से seeded है
- possible first UUIDs 2²⁵⁶ हैं
- collision की चिंता करने की जरूरत नहीं है
- frontend server द्वारा requests को backend servers में randomly assign करने वाले load balancing में भी unpredictable random numbers की जरूरत हो सकती है
- अगर attacker assignment observe करे और predictable algorithm जानता हो, तो वह expensive requests को किसी specific backend पर concentrate कर सकता है
- Go 1 generator में यह rare लेकिन possible problem है
- Go 1.22 में यह समस्या नहीं रहती
performance characteristics
- ChaCha8Rand के security benefits की छोटी cost है, लेकिन performance Go 1 generator और PCG जैसी ही range में है
- तुलना के लिए दो operations हैं
Uint64: random stream से nextuint64return करनाN(1000):[0, 1000)range का random number return करना
- 64-bit x86 chip पर
GOARCH=386से build कर 32-bit mode में चलाने पर PCG की 128-bit multiplication के कारण PCG, ChaCha8Rand से धीमा होता है- ChaCha8Rand 32-bit SIMD arithmetic का उपयोग करता है
- कुछ systems में
Go 1: Uint64,PCG: Uint64से तेज है, लेकिनGo 1: N(1000),PCG: N(1000)से धीमा है- Go 1 का
N(1000)range reduction के लिए 64-bit integer division दो बार इस्तेमाल करता है - PCG और ChaCha8 का
N(1000)ज्यादा तेजmath/rand/v2algorithm इस्तेमाल करता है, जो ज्यादातर division से बचता है
- Go 1 का
- कुल मिलाकर ChaCha8Rand Go 1 generator से धीमा है, लेकिन 2x से ज्यादा धीमा नहीं होता
- सामान्य servers में अंतर 3ns से अधिक नहीं होता, और बहुत कम programs में यह अंतर bottleneck बनेगा
निष्कर्ष
- Go 1.22 बिना code changes के programs की security बढ़ाता है
- core तरीका यह है कि
crypto/randके बजाय गलती सेmath/randइस्तेमाल करने की common problem कम करने के लिएmath/randको ही मजबूत किया गया है - npm
keypairpackage जैसे examples भी हैं, जहां Web Crypto API न होने पर JavaScriptMath.randomसे RSA key pair generate करने की कोशिश की गई - system security इस assumption पर निर्भर नहीं रह सकती कि developers गलती नहीं करेंगे
- Go 1.22 का ChaCha8Rand दिखाता है कि “mathematical” random numbers के लिए भी cryptographically strong pseudorandom number generator इस्तेमाल करने का approach दूसरे generators से competitive performance दे सकता है
1 टिप्पणियां
Hacker News की राय
लेख में बताए गए अनुसार, rclone में ठीक यही गलती हुई थी
crypto/randकेReadका इस्तेमाल करने वाले कोड को refactor करते समय import अपने-आप बदल गया, और शायदmath/randइस्तेमाल करने वाले कोड के साथ मिल जाने परgoimportsने इसेmath/randमें बदल दियानतीजतन secure random number generator की जगह, rclone ने समय से seed किया गया deterministic generator इस्तेमाल करना शुरू कर दिया, और यह diff में पकड़ में नहीं आया :-(
https://www.cvedetails.com/cve/CVE-2020-28924/
इसलिए मैं इस बदलाव का पूरी तरह समर्थन करता हूँ
goimportsकोcrypto/randको प्राथमिकता देने के लिए बदला गया था, इसलिए refactor के दौरान वास्तव में क्या हुआ यह पक्का नहीं हैशायद उसी फ़ाइल में
math/rand-विशेष API इस्तेमाल करने वाला कोड आ गया होगाhttps://go-review.googlesource.com/24847
वैसे भी, अच्छा है कि अब इस हिस्से को साफ़ किया जा रहा है
math/randइस्तेमाल हुआ है. असल में ऐसा नहीं था, बस कई फ़ाइलों में भ्रम हो गया था, इसलिए कोई बड़ा नुकसान नहीं हुआ, लेकिन इससे पता चलता है कि पूरी चीज़ कितनी उलझाऊ हैtext/templateऔरhtml/templateभी ऐसे ही हैं. पीछे मुड़कर देखें तो इस तरह की package name shadowing बुरा विचार था"secure password generation golang"खोजने पर मैंने देखा कि लगभग हर examplemath/randका उपयोग करता हैइससे भी बुरी बात यह कि सब password बनाने से ठीक पहले current time से seed initialize करते हैं
हमारे कोड में किसी को
math/randइस्तेमाल करते देखकर, यह जानने के लिए कि उसने कहाँ से copy किया, मैंने खोजा और तब यह दिखाgoimportsने लगभग शुरुआत से हीmath/rand.Readऔरcrypto/rand.Readको special-case किया हैलेकिन 2016 के https://github.com/golang/tools/commit/0835c735343e0d8e375f0... को देखें तो उस समय का ज़िक्र है जब
"rand.Read"को"math/rand"के रूप में resolve किया जा सकता थाशायद यह उसी दौर में हुआ होगा
"PredictableRand"जैसे नाम वाला API call देना इतना मुश्किल नहीं लगतापिछले हफ़्ते भी spacey ने https://news.ycombinator.com/item?id=40237491 पर इसे पोस्ट किया था, लेकिन लगता है वह पोस्ट गलती से https://news.ycombinator.com/item?id=40224864 की duplicate मानकर दब गई
go.dev ब्लॉग की ये दोनों पोस्ट एक ही series की दो कड़ियाँ हैं, लेकिन काफ़ी अलग हैं. यह पोस्ट efficient secure random number generation algorithm के बारे में है, जबकि पिछली पोस्ट Go API design के बारे में थी
Russell Cox लगातार बेहतरीन technical blog posts, proposals और काम प्रकाशित करते हैं
अगर आप अपनी writing और thinking की clarity बढ़ाना चाहते हैं, तो Russell Cox से शुरू करना अच्छा रहेगा
उस समय मुझे यह भी नहीं पता था कि Russ Cox कौन हैं, लेकिन वह लेख-श्रृंखला सचमुच शानदार थी
regular expression implementation पर मुफ्त में उपलब्ध सामग्री में शायद वह सबसे उच्च गुणवत्ता की है, और उसके बाद कई compiler-केंद्रित किताबें आती हैं, लेकिन वे न तो मुफ्त हैं और न ही वेब पर आसानी से खोजी जा सकती हैं
मैंने भी एक बार वहाँ
math/randइस्तेमाल कर दिया था जहाँcrypto/randअनिवार्य थानतीजतन dnscrypt-proxy2 के शुरुआती versions में static keys इस्तेमाल हुईं
कारण था import अपने-आप जोड़ने वाला VSCode extension. जिन सभी source files में secure random की ज़रूरत थी, उनमें मैंने सावधानी से
crypto/randimport किया था, लेकिन एक फ़ाइल में यह छूट गया, सब कुछ compile भी हो गया और ठीक चला, और मैं यह नहीं देख पाया कि उस खास फ़ाइल में extension ने चुपचापmath/randimport जोड़ दिया थाउसके बाद से, गलत
randके auto-import से बचने के लिए मैंcrypto/randकोcryptorandalias के साथ import करता हूँवैसे, Zig भी ChaCha8-आधारित random generator इस्तेमाल करता है, और cryptographic operations में user अपना generator नहीं दे सकता; हमेशा सुरक्षित generator ही उपयोग होता है. testing के लिए कुछ functions explicit seed लेते हैं
constrained environments के लिए standard library में Ascon permutation और Reverie construction पर आधारित एक छोटा generator भी शामिल है
2016 में
goimportsकोmath/randपरcrypto/randको प्राथमिकता देने के लिए बदला गया था(https://go-review.googlesource.com/24847), और उस समय Go के लिए VSCode support आया भी नहीं था2020 के दशक में भी मैं अक्सर सोचता रहा हूँ कि कई programming languages के default random implementations अब भी LFSR, MT जैसे तेज random generators क्यों इस्तेमाल करती हैं
मुझे लगता है कि बेहतर यह होगा कि conservative approach अपनाई जाए—यह मानकर कि लोगों को यह नहीं पता होता कि उन्हें pseudo-random generator चाहिए या cryptographically secure pseudo-random generator—और default को बाद वाले पर बदला जाए, जबकि पहले वाले की ज़रूरत वाले लोग उसे explicitly चुनें
अगर developer इस्तेमाल होने वाला random engine explicitly नहीं चुनता, तो उसे cryptographically secure generator मिलता है
अब मुश्किल हिस्सा लोगों को नए API पर migrate करने के लिए मनाना है। इससे भी आगे, global
Mt19937instance का इस्तेमाल करने वालेmt_rand()से, PHP 7.0 से पहले से उपलब्ध CSPRNG-आधारितrandom_int()पर ले जाना भी आसान नहीं है[1] https://www.php.net/releases/8.2/en.php#random_extension
मेरे use case में components की संख्या कई दसियों हज़ार थी, और profiling करने पर पता चला कि data structure initialization time का बड़ा हिस्सा
crypto/randकीRead()में जा रहा था, और मेरे MacBook पर वह system calls कर रही थीlibrary को patch करके
math/randकीRead()इस्तेमाल करवाई, तो performance काफ़ी बेहतर हो गईmath/randके तेज होने के अलावा, मुझे यह चिंता भी थी कि कहीं बिना वजह system का entropy pool खत्म न हो जाए। इस मामले में IDs के random होने की एकमात्र वजह यह थी कि data structure को serialize/deserialize करने के बाद बाद में और components जोड़े जा सकें, और मेरा ऐसा करने का इरादा नहीं थाइस ब्लॉग में बताए गए बदलाव का timing मेरे अनुभव से ठीक कैसे मेल खाता है, यह मुझे नहीं पता। शायद मैंने library का पुराना version इस्तेमाल किया था, और अगर अब
crypto/randव्यवहारिक रूप सेmath/randसे अलग पहचान में नहीं आता, तो ठीक ही है :-)state size अब भी काफ़ी बड़ी है (64 bytes बनाम 16 bytes), लेकिन
mt19937या पुराने Go PRNG जैसी चीज़ों से कहीं बेहतर हैअगर CSPRNG बहुत धीमा होता, जैसा कि reduced-round ChaCha variants के बजाय सामान्य CSPRNG में अक्सर होता है, तो default के रूप में उसका आकर्षण कम हो जाता
एक और छोटा कारण है कि लोग seed की ज़रूरत न होने पर भी PRNG की तरफ़ धकेले जाते हैं। CSPRNG API में हमेशा ऐसी errors होती हैं जिन्हें system call failure या entropy shortage के लिए handle करना पड़ता है
crypto/randreads वास्तव में कितनी बार fail होती हैं? आधुनिक systems में entropy खत्म करने के लिए कितना ज़्यादा पढ़ना पड़ता है? मैंने अरबों requests में कभी failure नहीं देखा, औरddभी ठीक काम करता हैमुझे यह भी जिज्ञासा है कि ज़्यादातर use cases के लिए
Must/panicstyle API ही शायद default होनी चाहिएवैसे, मैंने Python का
secretspackage (https://docs.python.org/3/library/secrets.html) देखा, और उसमें exceptions throw होने की कोई बात ही नहीं है। क्या व्यावहारिक रूप से ऐसा होता ही नहीं?थोड़ी performance खोने के बदले यह कहीं ज़्यादा मज़बूत गारंटी मिलती है कि गलत random generator इस्तेमाल करके कोई disaster नहीं होगा
अफ़सोस की बात है कि लगभग हर language में developers को अब भी इस sharp edge का ध्यान रखना पड़ता है
जो लोग नहीं जानते, उनके लिए:
gosecऔर उसका extensiongolangci-lint,math/randके इस्तेमाल पर warning देते हैंhttps://github.com/securego/gosec/blob/d3b2359ae29fe344f4df5...
math/rand/v2की जो बात मुझे सबसे ज़्यादा पसंद है, उनमें से एक यह है कि इसे कंपनी मेंnolintdirective और उसके बाद होने वाली PR discussion के बिना इस्तेमाल किया जा सकता हैमैं अभी भी security और नए v2 option के बारे में recommendation को समझने की कोशिश कर रहा हूँ
ब्लॉग पोस्ट में “secret values के लिए कुछ और चाहिए” जैसी पंक्तियाँ हैं, और फिर वह cryptographic randomness, ChaCha8, और system randomness से seeding तक विस्तार से बात करती है, इसलिए कुल मिलाकर बहुत “safe” होने का impression बनता है
लेकिन package docs में यह लिखा है
... but it should not be used for security-sensitive work ... This package's outputs might be easily predictable regardless of how it's seeded. For random numbers suitable for security-sensitive work, see the crypto/rand package.तो फिर ब्लॉग पोस्ट ऐसा संकेत क्यों देती है मानो
math/rand/v2को “secret values” के लिए इस्तेमाल किया जा सकता हो?क्या संक्षेप में मतलब यह है कि sensitive चीज़ों के लिए अब भी हर हाल में
crypto/randही इस्तेमाल करना चाहिए, और यहाँ बताए गए improvements बस एक safety net हैं, अगर कोईmath/rand/v2का गलत इस्तेमाल कर बैठे?math/rand/v2best choice नहीं है, लेकिन अब ऐसा नहीं रहा कि जहाँcrypto/randइस्तेमाल होना चाहिए था, वहाँ गलती से इसे इस्तेमाल करने पर तुरंत घातक security flaw बन जाएलेख में भी यही कहा गया है
crypto/randइस्तेमाल करना अब भी बेहतर है। operating system kernel कई snooping attacks से random values को secret रखने का बेहतर काम कर सकता है, kernel generator में लगातार नई entropy जोड़ता रहता है, और उस पर अधिक समीक्षा हो चुकी है। लेकिन गलती सेmath/randइस्तेमाल करना अब सुरक्षा आपदा नहीं रहासबसे खराब benchmark में भी नई strategy, unsafe random number generator की तुलना में लगभग आधी ही धीमी थी, और ज़्यादातर benchmark में अंतर इससे कहीं कम था
Go, standard library और उसके ऊपर बनने वाले apps के लिए सुरक्षा और performance के संतुलन को अच्छी तरह बनाए रखता है। अच्छा होगा अगर दूसरे ecosystem भी इसका अनुसरण करें
अगर किसी application को तेज़ लेकिन unsafe random numbers चाहिए, तो उसे अपना internal generator खुद implement करना होगा
आसानी से उपलब्ध unsafe random numbers रखना एक ऐसा खुद के पैर पर कुल्हाड़ी मारने वाला tool है जिसे हटाया जा सकता है
लोगों को यह मानने के लिए प्रोत्साहित करना कि
"random"primitive cryptographically safe है, खराब practice को बढ़ावा देना हैmath/rand/v2को cryptographically safe बनाना एक समस्या का समाधान कर सकता है, लेकिन अब वह चीज़ भी “ठीक” मानी जाने लगेगी जो देखने में security का वादा करती हुई नहीं लगतीसामान्य तौर पर
math/randfunctions के बारे में यह परंपरा नहीं रही है कि वे cryptographically safe हों। इसे बदलकर खराब code को संयोग से सही तरह काम करने देना, यह छिपा सकता है कि अगर हम ऐसी स्पष्ट गलती कर रहे हैं, तो और कौन-सी गलतियाँ भी कर रहे होंगेGo 1 का
math/rand, ज़्यादा सटीक रूप से, additive lagged Fibonacci generator कहलाना चाहिएइसका पहला परिचय Green, Smith, Klem के paper में हुआ था
[1] https://doi.org/10.1145/320998.321006
https://www.leviathansecurity.com/blog/attacking-gos-lagged-... में भी इसे lagged Fibonacci generator कहा गया है
कुछ महीने पहले Rob Pike और मैंने Go 1 generator के मूल C version के लेखक Don Mitchell से email पर बात की और पूछा कि वह इस algorithm को कैसे describe करेंगे, तो उनका जवाब था, “जहाँ तक मुझे याद है, Jim और मैंने Marsaglia जैसे LFSR generator को implement किया था”
दोनों विवरण—lagged Fibonacci और LFSR-जैसा generator—अलग-अलग दृष्टिकोण से सही लगते हैं। दोनों में से कोई भी ठीक है, लेकिन लेख में मूल लेखक का विवरण इस्तेमाल करने का फैसला किया गया
अगर एक छोटी-सी कमी बतानी हो, तो यहाँ statistical randomness और pseudo-random number generator को शायद मिलाकर इस्तेमाल किया गया है
Wikipedia पर statistical randomness की परिभाषा है: “जब किसी number sequence में पहचानने योग्य pattern या regularity न हो, तो उसे statistically random कहा जाता है”
क्या यह परिभाषा true random number generator (TRNG) पर भी लागू होती है? उम्मीद तो यही होनी चाहिए। कम-से-कम लंबे समय में या चरम सीमा पर तो ऐसा होना ही चाहिए। नहीं तो वह TRNG नहीं है
TRNG को लंबे समय में “ऐसी number sequence” बनानी चाहिए जिसमें “पहचानने योग्य pattern या regularity न हो”
इसलिए statistical randomness का मतलब PRNG नहीं होता, लेकिन यह कहा जा सकता है कि यह TRNG पर भी लागू हो सकता है
समस्या शायद इस वजह से आती है कि PRNG में सीमित रूप की statistical randomness की जाँच करने के लिए statistical randomness tests बहुत हैं
इसलिए PRNG की पहचान करने के लिए “statistical randomness” की जगह “pseudo-random number generator” कहना ज़्यादा उचित होता। फिर भी यह बहुत छोटी-सी कमी है