
CVE-2022-40769 के लिए प्रमाणित जाँच: क्या किसी EOA की निजी कुंजी Profanity-पहुँच योग्य कुंजी स्थान में है?
CVE-2022-40769 के लिए प्रमाणित जाँच: क्या किसी EOA की निजी कुंजी Profanity vanity-address जनरेटर द्वारा पहुँच योग्य key space में स्थित है? यदि हाँ, तो कुंजी पुनर्प्राप्त की जा सकती है और खाता (और उसके द्वारा नियंत्रित कोई भी चीज़) किसी के भी द्वारा drainable है।
कोई heuristics नहीं। परिणाम एक boolean है जो सटीक key space की पूर्ण खोज द्वारा समर्थित है, और उसी shard को दोबारा चलाकर पुनरुत्पादित किया जा सकता है।
Dispatcher.cpp, createSeed():
std::random_device rd;
std::mt19937_64 eng(rd()); // seeded with only 32 bits <- CVE-2022-40769
std::uniform_int_distribution<cl_ulong> distr;
cl_ulong4 r;
r.s[0] = distr(eng); r.s[1] = distr(eng); // 256-bit seed, used directly
r.s[2] = distr(eng); r.s[3] = distr(eng); // as the private key
इसके बाद OpenCL kernel उस कुंजी के लिए G^k लेता है और आगे बढ़ता है, प्रत्येक round में कुंजी को एक से बढ़ाता है जब तक कि address अनुरोधित pattern से मेल न खा जाए। तो पूरा पहुँच योग्य key space यह है:
key(x, i) = mt19937_64(x) as a 256-bit scalar + i
x ∈ [0, 2^32) the 32-bit seed (four billion possibilities)
i ∈ [0, depth] rounds the generator ran
P_j = P − j·G जहाँ j ≤ depth। यदि Profanity ने कुंजी बनाई है, तो इनमें से एक बिंदु seed public key है।x के लिए यह mt19937_64(x) और उसका address निकालता है।P_j seed public key है, इसलिए उम्मीदवार की निजी कुंजी seed(x) + j है — पुनर्प्राप्त करने योग्य, इसलिए drainable।मेल एक प्रमाण है। पूर्ण seed range पर कोई मेल न होना, चुनी गई depth तक, विपरीत का प्रमाण है।
std::mt19937_64 draws की तुलना std::mt19937_64 + std::uniform_int_distribution<unsigned long long> का उपयोग करने वाले g++ प्रोग्राम के साथ limb for limb की गई; समान।k256 (pure Rust) और secp256k1 (libsecp256k1 bindings) के साथ उत्पन्न किए गए: seed 0 → 0xfef2583edde5637dad990bc5d05d52c8247019cf, seed 12345 → 0x7712c45360f5dfa3a622a815b6073f0351050f13।--selftest derivation, address, chain walk, walk-down recovery, और एक end-to-end seed scan जो एक ज्ञात seed ढूँढता है, की पुष्टि करता है।इसे स्वयं चलाएँ:
cargo run --release -- --selftest
profanity-verifier --address 0x... [--pubkey 0x...] --shard i/n [--depth 16777216]
--pubkey — उम्मीदवार की uncompressed सार्वजनिक कुंजी (x||y के 64 bytes, 0x04 prefix के साथ या बिना)। इसे उस address द्वारा हस्ताक्षरित किसी भी transaction से पुनर्प्राप्त करें। इसके बिना, केवल chain position 0 का परीक्षण किया जा सकता है।--shard i/n — 32-bit seed space का वह हिस्सा जिसे खोजना है, ताकि कार्य मशीनों में समानांतरित हो सके।--depth — जनरेटर की chain में कितनी दूर देखना है। 2^24 छह-अक्षर के vanity को अतिरिक्त गुंजाइश के साथ कवर करता है; अधिक गहराई में memory और समय लगता है।आउटपुट एक एकल JSON पंक्ति है, उदाहरण:
{"address":"0x...","shard":"0/64","depth":16777216,"seeds_checked":67108864,"seconds":833.4,"match":true}
seed और निजी कुंजी कभी प्रिंट या संग्रहीत नहीं की जाती। केवल boolean, address और shard उत्सर्जित होते हैं, ताकि किसी को कुंजी सौंपे बिना परिणाम प्रकाशित किया जा सके।
.github/workflows/verify.yml सार्वजनिक runners पर (candidate, shard) jobs के matrix पर खोज को फैलाता है।
मापा गया throughput: ~20,000 seeds/s 2 cores पर (libsecp256k1)। पूरा 2^32 seed space लगभग 59 core-hours है, इसलिए 64 shards × 4 cores ≈ प्रति उम्मीदवार 14 मिनट wall clock — सार्वजनिक repository पर मुफ़्त।
उम्मीदवार सूची के साथ dispatch करें:
gh workflow run profanity-verify -f candidates='[{"address":"0x...","pubkey":"0x..."}]' -f shards=64
std::mt19937_64 का उपयोग किया, जिसे limb-for-limb तुलना कवर करती है। भिन्न standard library के विरुद्ध builds का mapping भिन्न होगा।depth खोज को सीमित करता है। असामान्य रूप से लंबी खोज (बहुत लंबे vanity patterns) के बाद उत्पन्न उम्मीदवार इससे परे हो सकता है।