
शुद्ध पायथन ECDSA हस्ताक्षर/सत्यापन और ECDH कुंजी समझौता
यह ECC (एलिप्टिक कर्व क्रिप्टोग्राफी) का उपयोग करने में आसान कार्यान्वयन है, जिसमें ECDSA (एलिप्टिक कर्व डिजिटल सिग्नेचर एल्गोरिथ्म), EdDSA (एडवर्ड्स-कर्व डिजिटल सिग्नेचर एल्गोरिथ्म) और ECDH (एलिप्टिक कर्व डिफी-हेलमैन) के लिए समर्थन है, जो विशुद्ध रूप से Python में लागू किया गया है, और MIT लाइसेंस के अंतर्गत जारी किया गया है। इस लाइब्रेरी से आप शीघ्रता से कुंजी जोड़े (साइनिंग कुंजी और वेरिफाइंग कुंजी) बना सकते हैं, संदेशों पर हस्ताक्षर कर सकते हैं और हस्ताक्षर सत्यापित कर सकते हैं। आप विनिमय की गई सार्वजनिक कुंजियों के आधार पर साझा गुप्त कुंजी पर भी सहमत हो सकते हैं। कुंजियाँ और हस्ताक्षर बहुत छोटे होते हैं, जिससे उन्हें संभालना और अन्य प्रोटोकॉल में शामिल करना आसान होता है।
नोट: इस लाइब्रेरी का उपयोग प्रोडक्शन सेटिंग्स में नहीं किया जाना चाहिए, अधिक जानकारी के लिए सुरक्षा देखें।
यह लाइब्रेरी कुंजी निर्माण, हस्ताक्षर, सत्यापन, और साझा गुप्त
व्युत्पत्ति प्रदान करती है पाँच
लोकप्रिय NIST "Suite B" GF(p) (प्राइम फ़ील्ड) वक्रों के लिए, जिनकी कुंजी लंबाई 192,
224, 256, 384, और 521 बिट है। इन वक्रों के "शॉर्ट नाम", जैसा कि
OpenSSL टूल (openssl ecparam -list_curves) से ज्ञात है, हैं: prime192v1,
secp224r1, prime256v1, secp384r1, और secp521r1। इसमें
Bitcoin द्वारा उपयोग किया जाने वाला 256-बिट वक्र secp256k1 शामिल है। साथ ही
160 से 512 बिट तक के Brainpool वक्रों के नियमित (गैर-मुड़े) संस्करणों के लिए भी समर्थन है।
उन वक्रों के "शॉर्ट नाम" हैं: brainpoolP160r1, brainpoolP192r1,
brainpoolP224r1, brainpoolP256r1, brainpoolP320r1, brainpoolP384r1,
। SEC मानक के कुछ छोटे वक्र भी
शामिल हैं (मुख्य रूप से लाइब्रेरी के परीक्षण को तेज़ करने के लिए), वे हैं:
, , , और ।
कुंजी निर्माण, हस्ताक्षर और सत्यापन Ed25519 और के लिए भी समर्थित है
Ed448 वक्रों के लिए।
कोई अन्य वक्र शामिल नहीं हैं, लेकिन प्राइम फ़ील्ड पर और अधिक वक्रों के लिए
समर्थन जोड़ना बहुत कठिन नहीं है।
यह लाइब्रेरी केवल Python और 'six' पैकेज का उपयोग करती है। यह Python 2.6, 2.7, और 3.6+ के साथ संगत है। यह वैकल्पिक कार्यान्वयन जैसे pypy और pypy3 पर निष्पादन का भी समर्थन करती है।
यदि gmpy2 या gmpy स्थापित है, तो उनका उपयोग तेज़ अंकगणित के लिए किया जाएगा।
इनमें से किसी को भी इस लाइब्रेरी के स्थापित होने के बाद स्थापित किया जा सकता है,
python-ecdsa स्टार्ट-अप पर उनकी उपस्थिति का पता लगाएगा और उन्हें
स्वचालित रूप से उपयोग करेगा।
इष्टतम प्रदर्शन के लिए आपको Python3 पर gmpy2 को प्राथमिकता देनी चाहिए।
OpenSSL संगतता परीक्षण चलाने के लिए, 'openssl' टूल आपके
PATH में होना चाहिए। इस रिलीज़ का परीक्षण OpenSSL 0.9.8o,
1.0.0a, 1.0.2f, 1.1.1d और 3.0.1 (अन्य के अलावा) के विरुद्ध सफलतापूर्वक किया गया है।
यह लाइब्रेरी PyPI पर उपलब्ध है, इसे pip का उपयोग करके स्थापित करने की अनुशंसा की जाती है:```
pip install ecdsa
यदि उच्च प्रदर्शन की आवश्यकता हो और नेटिव कोड का उपयोग करने में कोई समस्या न हो, तो `gmpy2` के साथ इंस्टॉलेशन निर्दिष्ट करना संभव है:```
pip install ecdsa[gmpy2]
या (धीमा, लीगेसी विकल्प):``` pip install ecdsa[gmpy]
## गति
निम्न तालिका दर्शाती है कि यह लाइब्रेरी कुंजी जोड़े उत्पन्न करने
(`keygen`), डेटा पर हस्ताक्षर करने (`sign`), उन हस्ताक्षरों को सत्यापित करने (`verify`),
एक साझा रहस्य निकालने (`ecdh`), और
बिना कुंजी-विशिष्ट पूर्व-गणना के हस्ताक्षर सत्यापित करने (`no PC verify`) में कितना समय लेती है।
ये सभी मान सेकंड में हैं।
सुविधा के लिए, इन मानों के व्युत्क्रम भी दिए गए हैं:
प्रति सेकंड कितनी कुंजियाँ उत्पन्न की जा सकती हैं (`keygen/s`), प्रति सेकंड कितने हस्ताक्षर
किए जा सकते हैं (`sign/s`), प्रति सेकंड कितने हस्ताक्षर सत्यापित किए जा सकते हैं
(`verify/s`), प्रति सेकंड कितने साझा रहस्य निकाले जा सकते हैं
(`ecdh/s`), और बिना कुंजी-विशिष्ट पूर्व-गणना के प्रति सेकंड कितने हस्ताक्षर
सत्यापित किए जा सकते हैं (`no PC verify/s`)। कच्चे हस्ताक्षर का आकार
(सामान्यतः सबसे छोटा तरीका
जिसमें हस्ताक्षर को एन्कोड किया जा सकता है) भी `siglen` कॉलम में दिया गया है।
अपने स्वयं के कंप्यूटर पर यह तालिका उत्पन्न करने के लिए `tox -e speed` का उपयोग करें।
Intel Core i7 4790K @ 4.0GHz पर मुझे निम्नलिखित प्रदर्शन मिल रहा है:```
siglen keygen keygen/s sign sign/s verify verify/s no PC verify no PC verify/s
NIST192p: 48 0.00032s 3134.06 0.00033s 2985.53 0.00063s 1598.36 0.00129s 774.43
NIST224p: 56 0.00040s 2469.24 0.00042s 2367.88 0.00081s 1233.41 0.00170s 586.66
NIST256p: 64 0.00051s 1952.73 0.00054s 1867.80 0.00098s 1021.86 0.00212s 471.27
NIST384p: 96 0.00107s 935.92 0.00111s 904.23 0.00203s 491.77 0.00446s 224.00
NIST521p: 132 0.00210s 475.52 0.00215s 464.16 0.00398s 251.28 0.00874s 114.39
SECP256k1: 64 0.00052s 1921.54 0.00054s 1847.49 0.00105s 948.68 0.00210s 477.01
BRAINPOOLP160r1: 40 0.00025s 4003.88 0.00026s 3845.12 0.00053s 1893.93 0.00105s 949.92
BRAINPOOLP192r1: 48 0.00033s 3043.97 0.00034s 2975.98 0.00063s 1581.50 0.00135s 742.29
BRAINPOOLP224r1: 56 0.00041s 2436.44 0.00043s 2315.51 0.00078s 1278.49 0.00180s 556.16
BRAINPOOLP256r1: 64 0.00053s 1892.49 0.00054s 1846.24 0.00114s 875.64 0.00229s 437.25
BRAINPOOLP320r1: 80 0.00073s 1361.26 0.00076s 1309.25 0.00143s 699.29 0.00322s 310.49
BRAINPOOLP384r1: 96 0.00107s 931.29 0.00111s 901.80 0.00230s 434.19 0.00476s 210.20
BRAINPOOLP512r1: 128 0.00207s 483.41 0.00212s 471.42 0.00425s 235.43 0.00912s 109.61
SECP112r1: 28 0.00015s 6672.53 0.00016s 6440.34 0.00031s 3265.41 0.00056s 1774.20
SECP112r2: 28 0.00015s 6697.11 0.00015s 6479.98 0.00028s 3524.72 0.00058s 1716.16
SECP128r1: 32 0.00018s 5497.65 0.00019s 5272.89 0.00036s 2747.39 0.00072s 1396.16
SECP160r1: 42 0.00025s 3949.32 0.00026s 3894.45 0.00046s 2153.85 0.00102s 985.07
Ed25519: 64 0.00076s 1324.48 0.00042s 2405.01 0.00109s 918.05 0.00344s 290.50
Ed448: 114 0.00176s 569.53 0.00115s 870.94 0.00282s 355.04 0.01024s 97.69
ecdh ecdh/s
NIST192p: 0.00104s 964.89
NIST224p: 0.00134s 748.63
NIST256p: 0.00170s 587.08
NIST384p: 0.00352s 283.90
NIST521p: 0.00717s 139.51
SECP256k1: 0.00154s 648.40
BRAINPOOLP160r1: 0.00082s 1220.70
BRAINPOOLP192r1: 0.00105s 956.75
BRAINPOOLP224r1: 0.00136s 734.52
BRAINPOOLP256r1: 0.00178s 563.32
BRAINPOOLP320r1: 0.00252s 397.23
BRAINPOOLP384r1: 0.00376s 266.27
BRAINPOOLP512r1: 0.00733s 136.35
SECP112r1: 0.00046s 2180.40
SECP112r2: 0.00045s 2229.14
SECP128r1: 0.00054s 1868.15
SECP160r1: 0.00080s 1243.98
gmpy2 लोड के साथ प्रदर्शन का परीक्षण करने के लिए, tox -e speedgmpy2 का उपयोग करें।
उसी मशीन पर मुझे gmpy2 के साथ निम्नलिखित प्रदर्शन मिल रहा है:```
siglen keygen keygen/s sign sign/s verify verify/s no PC verify no PC verify/s
NIST192p: 48 0.00017s 5933.40 0.00017s 5751.70 0.00032s 3125.28 0.00067s 1502.41
NIST224p: 56 0.00021s 4782.87 0.00022s 4610.05 0.00040s 2487.04 0.00089s 1126.90
NIST256p: 64 0.00023s 4263.98 0.00024s 4125.16 0.00045s 2200.88 0.00098s 1016.82
NIST384p: 96 0.00041s 2449.54 0.00042s 2399.96 0.00083s 1210.57 0.00172s 581.43
NIST521p: 132 0.00071s 1416.07 0.00072s 1389.81 0.00144s 692.93 0.00312s 320.40
SECP256k1: 64 0.00024s 4245.05 0.00024s 4122.09 0.00045s 2206.40 0.00094s 1068.32
BRAINPOOLP160r1: 40 0.00014s 6939.17 0.00015s 6681.55 0.00029s 3452.43 0.00057s 1769.81
BRAINPOOLP192r1: 48 0.00017s 5920.05 0.00017s 5774.36 0.00034s 2979.00 0.00069s 1453.19
BRAINPOOLP224r1: 56 0.00021s 4732.12 0.00022s 4622.65 0.00041s 2422.47 0.00087s 1149.87
BRAINPOOLP256r1: 64 0.00024s 4233.02 0.00024s 4115.20 0.00047s 2143.27 0.00098s 1015.60
BRAINPOOLP320r1: 80 0.00032s 3162.38 0.00032s 3077.62 0.00063s 1598.83 0.00136s 737.34
BRAINPOOLP384r1: 96 0.00041s 2436.88 0.00042s 2395.62 0.00083s 1202.68 0.00178s 562.85
BRAINPOOLP512r1: 128 0.00063s 1587.60 0.00064s 1558.83 0.00125s 799.96 0.00281s 355.83
SECP112r1: 28 0.00009s 11118.66 0.00009s 10775.48 0.00018s 5456.00 0.00033s 3020.83
SECP112r2: 28 0.00009s 11322.97 0.00009s 10857.71 0.00017s 5748.77 0.00032s 3094.28
SECP128r1: 32 0.00010s 10078.39 0.00010s 9665.27 0.00019s 5200.58 0.00036s 2760.88
SECP160r1: 42 0.00015s 6875.51 0.00015s 6647.35 0.00029s 3422.41 0.00057s 1768.35
Ed25519: 64 0.00030s 3322.56 0.00018s 5568.63 0.00046s 2165.35 0.00153s 654.02
Ed448: 114 0.00060s 1680.53 0.00039s 2567.40 0.00096s 1036.67 0.00350s 285.62
ecdh ecdh/s
NIST192p: 0.00050s 1985.70
NIST224p: 0.00066s 1524.16
NIST256p: 0.00071s 1413.07
NIST384p: 0.00127s 788.89
NIST521p: 0.00230s 434.85
SECP256k1: 0.00071s 1409.95
BRAINPOOLP160r1: 0.00042s 2374.65 BRAINPOOLP192r1: 0.00051s 1960.01 BRAINPOOLP224r1: 0.00066s 1518.37 BRAINPOOLP256r1: 0.00071s 1399.90 BRAINPOOLP320r1: 0.00100s 997.21 BRAINPOOLP384r1: 0.00129s 777.51 BRAINPOOLP512r1: 0.00210s 475.99 SECP112r1: 0.00022s 4457.70 SECP112r2: 0.00024s 4252.33 SECP128r1: 0.00028s 3589.31 SECP160r1: 0.00043s 2305.02
(`gmpy` संस्करण भी है, इसे `tox -e speedgmpy` का उपयोग करके चलाएँ)
तुलना के लिए, एक अत्यधिक अनुकूलित कार्यान्वयन (कुछ वक्रों के लिए वक्र-विशिष्ट
असेंबली सहित), जैसे कि OpenSSL 1.1.1d में, समान मशीन पर निम्नलिखित
प्रदर्शन संख्याएँ प्रदान करता है।
इसे दोहराने के लिए `openssl speed ecdsa` और `openssl speed ecdh` चलाएँ:```
sign verify sign/s verify/s
192 bits ecdsa (nistp192) 0.0002s 0.0002s 4785.6 5380.7
224 bits ecdsa (nistp224) 0.0000s 0.0001s 22475.6 9822.0
256 bits ecdsa (nistp256) 0.0000s 0.0001s 45069.6 14166.6
384 bits ecdsa (nistp384) 0.0008s 0.0006s 1265.6 1648.1
521 bits ecdsa (nistp521) 0.0003s 0.0005s 3753.1 1819.5
256 bits ecdsa (brainpoolP256r1) 0.0003s 0.0003s 2983.5 3333.2
384 bits ecdsa (brainpoolP384r1) 0.0008s 0.0007s 1258.8 1528.1
512 bits ecdsa (brainpoolP512r1) 0.0015s 0.0012s 675.1 860.1
sign verify sign/s verify/s
253 bits EdDSA (Ed25519) 0.0000s 0.0001s 28217.9 10897.7
456 bits EdDSA (Ed448) 0.0003s 0.0005s 3926.5 2147.7
op op/s
192 bits ecdh (nistp192) 0.0002s 4853.4
224 bits ecdh (nistp224) 0.0001s 15252.1
256 bits ecdh (nistp256) 0.0001s 18436.3
384 bits ecdh (nistp384) 0.0008s 1292.7
521 bits ecdh (nistp521) 0.0003s 2884.7
256 bits ecdh (brainpoolP256r1) 0.0003s 3066.5
384 bits ecdh (brainpoolP384r1) 0.0008s 1298.0
512 bits ecdh (brainpoolP512r1) 0.0014s 694.8
कुंजियों और हस्ताक्षर को विभिन्न तरीकों से क्रमबद्ध (serialize) किया जा सकता है (नीचे उपयोग देखें)। NIST192p कुंजी के लिए, तीन बुनियादी निरूपणों के लिए निम्नलिखित लंबाई (बाइट्स में) की स्ट्रिंग्स आवश्यक होती हैं:
to_string: signkey= 24, verifykey= 48, signature=48
compressed: signkey=n/a, verifykey= 25, signature=n/a
DER: signkey=106, verifykey= 80, signature=55
PEM: signkey=278, verifykey=162, (no support for PEM signatures)
2006 में, पीटर पियर्सन (Peter Pearson) ने sci.crypt को संदेश में ECDSA का अपना शुद्ध-पायथन कार्यान्वयन घोषित किया, जो उनकी डाउनलोड साइट पर उपलब्ध है। 2010 में, ब्रायन वार्नर (Brian Warner) ने इस कोड के चारों ओर एक रैपर लिखा, ताकि इसे उपयोग करना थोड़ा आसान और सुरक्षित हो सके। 2020 में, हुबर्ट करियो (Hubert Kario) ने दीर्घवृत्तीय वक्र क्रिप्टोग्राफी का एक कार्यान्वयन शामिल किया जो आंतरिक रूप से जैकोबियन निर्देशांक का उपयोग करता है, जिससे प्रदर्शन लगभग 20 गुना बेहतर हो गया। आप इस रैपर के README को देख रहे हैं।
पूर्ण परीक्षण सूट चलाने के लिए, यह करें:
tox -e coverage
Intel Core i7 4790K @ 4.0GHz पर, परीक्षणों को निष्पादित होने में लगभग 18 सेकंड लगते हैं।
परीक्षण सूट
hypothesis का उपयोग करता है, इसलिए परीक्षण सूट के निष्पादन समय में कुछ अंतर्निहित परिवर्तनशीलता होती है।
test_pyecdsa.py और test_ecdh.py का एक भाग OpenSSL के साथ संगतता की जाँच करता है, "openssl" CLI टूल चलाकर; यदि आप इसके साथ संगतता का परीक्षण करना चाहते हैं तो सुनिश्चित करें कि यह आपके PATH में है (यदि OpenSSL गायब है, बहुत पुराना है, या ऊपरी रिलीज़ में समर्थित सभी वक्रों का समर्थन नहीं करता है, तो आपको उपरोक्त coverage रन में छोड़े गए परीक्षण (skipped tests) दिखाई देंगे)।
यह लाइब्रेरी सुरक्षा को ध्यान में रखकर डिज़ाइन नहीं की गई थी। यदि आप ऐसे डेटा को संसाधित कर रहे हैं जिसे संरक्षित करने की आवश्यकता है, तो हम सुझाव देते हैं कि आप OpenSSL के चारों ओर एक गुणवत्तापूर्ण रैपर का उपयोग करें। pyca/cryptography ऐसे ही रैपर का एक उदाहरण है। इस लाइब्रेरी का प्राथमिक उपयोग-मामला अंतर-संचालन परीक्षण के लिए एक पोर्टेबल लाइब्रेरी और एक शिक्षण उपकरण के रूप में है।
यह लाइब्रेरी साइड-चैनल हमलों से सुरक्षा नहीं करती है।
हमलावरों को यह मापने न दें कि आपको कुंजी युग्म उत्पन्न करने या संदेश पर हस्ताक्षर करने में कितना समय लगता है। हमलावरों को उसी भौतिक मशीन पर कोड चलाने न दें जब कुंजी युग्म निर्माण या हस्ताक्षर हो रहा हो (इसमें वर्चुअल मशीनें भी शामिल हैं)। हमलावरों को यह मापने न दें कि कुंजी युग्म उत्पन्न करते या संदेश पर हस्ताक्षर करते समय आपका कंप्यूटर कितनी बिजली का उपयोग करता है। हमलावरों को कुंजी युग्म उत्पन्न करते या संदेश पर हस्ताक्षर करते समय आपके कंप्यूटर से आने वाले RF व्यवधान को मापने न दें। ध्यान दें: केवल निजी कुंजी लोड करने से ही कुंजी युग्म निर्माण हो जाएगा। अन्य परिचालन या हमले के वेक्टर भी हमलों के प्रति संवेदनशील हो सकते हैं। एक परिष्कृत हमलावर के लिए, निजी कुंजी के साथ केवल एक परिचालन का अवलोकन करना निजी कुंजी को पूरी तरह से पुनर्निर्मित करने के लिए पर्याप्त होगा।
कृपया यह भी ध्यान दें कि कोई भी शुद्ध-पायथन क्रिप्टोग्राफ़िक लाइब्रेरी समान साइड-चैनल हमलों के प्रति संवेदनशील होगी। ऐसा इसलिए है क्योंकि Python साइड-चैनल-सुरक्षित प्रिमिटिव प्रदान नहीं करता है (hmac.compare_digest() के अपवाद के साथ), जिससे साइड-चैनल-सुरक्षित प्रोग्रामिंग असंभव हो जाती है।
यह लाइब्रेरी यादृच्छिक संख्याओं के एक मजबूत स्रोत पर निर्भर करती है। इसे ऐसी प्रणाली पर उपयोग न करें जहाँ os.urandom() क्रिप्टोग्राफ़िक रूप से सुरक्षित यादृच्छिक संख्याएँ प्रदान नहीं करता है।
आप एक SigningKey बनाकर शुरू करते हैं। आप इसका उपयोग डेटा पर हस्ताक्षर करने के लिए कर सकते हैं, डेटा को बाइट स्ट्रिंग के रूप में पास करके और हस्ताक्षर (जो कि बाइट स्ट्रिंग भी है) वापस प्राप्त करके। आप एक SigningKey से संबंधित VerifyingKey देने के लिए भी कह सकते हैं। VerifyingKey का उपयोग हस्ताक्षर सत्यापित करने के लिए किया जा सकता है, उसे डेटा स्ट्रिंग और हस्ताक्षर बाइट स्ट्रिंग दोनों पास करके: यह या तो True लौटाता है या BadSignatureError उठाता है।```python
from ecdsa import SigningKey
sk = SigningKey.generate() # uses NIST192p
vk = sk.verifying_key
signature = sk.sign(b"message")
assert vk.verify(signature, b"message")
प्रत्येक `SigningKey`/`VerifyingKey` एक विशिष्ट curve से संबद्ध होता है, जैसे
NIST192p (डिफ़ॉल्ट वाला)। लंबे curves अधिक सुरक्षित होते हैं, लेकिन उपयोग में अधिक समय
लेते हैं, और परिणामस्वरूप लंबी keys और signatures बनती हैं।```python
from ecdsa import SigningKey, NIST384p
sk = SigningKey.generate(curve=NIST384p)
vk = sk.verifying_key
signature = sk.sign(b"message")
assert vk.verify(signature, b"message")
SigningKey को कई अलग-अलग प्रारूपों में क्रमबद्ध किया जा सकता है: सबसे छोटा
तरीका s=sk.to_string() को कॉल करना है, और फिर इसे
SigningKey.from_string(s, curve) के साथ पुनः बनाना है . यह छोटा रूप वक्र को रिकॉर्ड नहीं करता,
इसलिए आपको from_string() को वही वक्र पास करना सुनिश्चित करना होगा जो आपने
मूल कुंजी के लिए उपयोग किया था. NIST192p-आधारित साइनिंग कुंजी का छोटा रूप केवल 24
बाइट लंबा होता है. यदि कोई बिंदु एन्कोडिंग अमान्य है या वह निर्दिष्ट वक्र पर स्थित नहीं है,
तो from_string() MalformedPointError उत्पन्न करेगा.```python
from ecdsa import SigningKey, NIST384p
sk = SigningKey.generate(curve=NIST384p)
sk_string = sk.to_string()
sk2 = SigningKey.from_string(sk_string, curve=NIST384p)
print(sk_string.hex())
print(sk2.to_string().hex())
नोट: जबकि विधियों को `to_string()` कहा जाता है, वे जो प्रकार लौटाती हैं वह
वास्तव में `bytes` है, "string" भाग Python 2 से अवशेष है।
`sk.to_pem()` और `sk.to_der()` हस्ताक्षर कुंजी को उन्हीं
प्रारूपों में क्रमबद्ध करेंगे जिन्हें OpenSSL उपयोग करता है। PEM फ़ाइल परिचित ASCII-armored
`"-----BEGIN EC PRIVATE KEY-----"` base64-एन्कोडेड प्रारूप की तरह दिखती है, और DER प्रारूप
उसी डेटा का एक छोटा बाइनरी रूप है।
`SigningKey.from_pem()/.from_der()` इस क्रमबद्धता को पूर्ववत करेंगे। ये
प्रारूपों में वक्र का नाम शामिल होता है, इसलिए आपको वक्र
पहचानकर्ता डीसेरिएलाइज़र में पास करने की आवश्यकता नहीं है। यदि फ़ाइल विकृत है, तो `from_der()`
और `from_pem()` `UnexpectedDER` या` MalformedPointError` उठाएंगे।```python
from ecdsa import SigningKey, NIST384p
sk = SigningKey.generate(curve=NIST384p)
sk_pem = sk.to_pem()
sk2 = SigningKey.from_pem(sk_pem)
# sk and sk2 are the same key
इसी प्रकार, VerifyingKey को उसी तरह क्रमबद्ध किया जा सकता है:
vk.to_string()/VerifyingKey.from_string(), to_pem()/from_pem(), और
to_der()/from_der()। VerifyingKey.from_string() के लिए भी वही curve= तर्क आवश्यक है।```python
from ecdsa import SigningKey, VerifyingKey, NIST384p
sk = SigningKey.generate(curve=NIST384p)
vk = sk.verifying_key
vk_string = vk.to_string()
vk2 = VerifyingKey.from_string(vk_string, curve=NIST384p)
from ecdsa import SigningKey, VerifyingKey, NIST384p sk = SigningKey.generate(curve=NIST384p) vk = sk.verifying_key vk_pem = vk.to_pem() vk2 = VerifyingKey.from_pem(vk_pem)
हस्ताक्षर की गणना करने के कुछ अलग तरीके हैं। मूल रूप से, ECDSA एक संख्या लेता है जो हस्ताक्षरित किए जा रहे डेटा को दर्शाती है, और संख्याओं की एक जोड़ी लौटाता है जो हस्ताक्षर को दर्शाती है। `sk.sign()` और `vk.verify()` के लिए `hashfunc=` तर्क का उपयोग किसी भी स्ट्रिंग को एक निश्चित-लंबाई वाले डाइजेस्ट में बदलने के लिए किया जाता है, जिसे फिर एक संख्या में बदल दिया जाता है जिस पर ECDSA हस्ताक्षर कर सकता है, और sign तथा verify दोनों को एक ही दृष्टिकोण का उपयोग करना चाहिए। डिफ़ॉल्ट मान `hashlib.sha1` है, लेकिन यदि आप NIST256p या उससे लंबे वक्र का उपयोग करते हैं, तो आप इसके बजाय `hashlib.sha256` का उपयोग कर सकते हैं।
हस्ताक्षर को दर्शाने के भी कई तरीके हैं। डिफ़ॉल्ट `sk.sign()` और `vk.verify()` विधियाँ इसे सरलता और न्यूनतम ओवरहेड के लिए एक छोटी स्ट्रिंग के रूप में प्रस्तुत करती हैं। किसी भिन्न योजना का उपयोग करने के लिए, `sk.sign(sigencode=)` और `vk.verify(sigdecode=)` तर्कों का उपयोग करें। `ecdsa.util` मॉड्यूल में सहायक फ़ंक्शन हैं जो यहाँ उपयोगी हो सकते हैं।
"seed" से `SigningKey` बनाना भी संभव है, जो नियतात्मक (deterministic) है। इसका उपयोग उन प्रोटोकॉल में किया जा सकता है जहाँ आप किसी अन्य गुप्त से लगातार साइनिंग कुंजियाँ प्राप्त करना चाहते हैं, उदाहरण के लिए जब आप तीन अलग-अलग कुंजियाँ चाहते हैं और केवल एक मास्टर गुप्त संग्रहीत करना चाहते हैं। आपको लगभग `curve.baselen` बाइट्स एंट्रॉपी वाले एक समान रूप से वितरित, अनुमान लगाने में असमर्थ seed से शुरू करना चाहिए, और फिर इसे सही सीमा में एक पूर्णांक में बदलने के लिए `ecdsa.util` में दिए गए सहायक फ़ंक्शनों में से एक का उपयोग करें, और अंत में इसे `SigningKey.from_secret_exponent()` में पास करें, इस प्रकार:```python
import os
from ecdsa import NIST384p, SigningKey
from ecdsa.util import randrange_from_seed__trytryagain
def make_key(seed):
secexp = randrange_from_seed__trytryagain(seed, NIST384p.order)
return SigningKey.from_secret_exponent(secexp, curve=NIST384p)
seed = os.urandom(NIST384p.baselen) # or other starting point
sk1a = make_key(seed)
sk1b = make_key(seed)
# note: sk1a and sk1b are the same key
assert sk1a.to_string() == sk1b.to_string()
sk2 = make_key(b"2-"+seed) # different key
assert sk1a.to_string() != sk2.to_string()
यदि एप्लिकेशन एक ही कुंजी के साथ बनाए गए कई हस्ताक्षरों को सत्यापित करेगा, तो हस्ताक्षर सत्यापन को काफी तेज़ बनाने के लिए कुछ आंतरिक मानों की पूर्व-गणना करना संभव है। ब्रेक-ईवन बिंदु लगभग 100 सत्यापित हस्ताक्षरों पर आता है।
पूर्व-गणना करने के लिए, आप VerifyingKey इंस्टेंस पर precompute() विधि
को कॉल कर सकते हैं:```python
from ecdsa import SigningKey, NIST384p
sk = SigningKey.generate(curve=NIST384p)
vk = sk.verifying_key
vk.precompute()
signature = sk.sign(b"message")
assert vk.verify(signature, b"message")
एक बार `precompute()` को कॉल करने के बाद, इस कुंजी के साथ सभी हस्ताक्षर सत्यापन तेजी से निष्पादित होंगे।
## OpenSSL अनुकूलता
OpenSSL उपकरणों द्वारा सत्यापित किए जा सकने वाले हस्ताक्षर बनाने के लिए, या उन उपकरणों द्वारा निर्मित हस्ताक्षरों को सत्यापित करने के लिए, उपयोग करें:```python
# openssl ecparam -name prime256v1 -genkey -out sk.pem
# openssl ec -in sk.pem -pubout -out vk.pem
# echo "data for signing" > data
# openssl dgst -sha256 -sign sk.pem -out data.sig data
# openssl dgst -sha256 -verify vk.pem -signature data.sig data
# openssl dgst -sha256 -prverify sk.pem -signature data.sig data
import hashlib
from ecdsa import SigningKey, VerifyingKey
from ecdsa.util import sigencode_der, sigdecode_der
with open("vk.pem") as f:
vk = VerifyingKey.from_pem(f.read())
with open("data", "rb") as f:
data = f.read()
with open("data.sig", "rb") as f:
signature = f.read()
assert vk.verify(signature, data, hashlib.sha256, sigdecode=sigdecode_der)
with open("sk.pem") as f:
sk = SigningKey.from_pem(f.read(), hashlib.sha256)
new_signature = sk.sign_deterministic(data, sigencode=sigencode_der)
with open("data.sig2", "wb") as f:
f.write(new_signature)
# openssl dgst -sha256 -verify vk.pem -signature data.sig2 data
नोट: यदि OpenSSL 1.0.0 या उससे पहले के संस्करण के साथ संगतता आवश्यक है, तो
sigencode_string और sigdecode_string को ecdsa.util से क्रमशः
हस्ताक्षर लिखने और पढ़ने के लिए उपयोग किया जा सकता है।
कुंजियों को भी उस प्रारूप में लिखा जा सकता है जिसे openssl संभाल सकता है:```python from ecdsa import SigningKey, VerifyingKey
with open("sk.pem") as f: sk = SigningKey.from_pem(f.read()) with open("sk.pem", "wb") as f: f.write(sk.to_pem())
with open("vk.pem") as f: vk = VerifyingKey.from_pem(f.read()) with open("vk.pem", "wb") as f: f.write(vk.to_pem())
## एन्ट्रॉपी
`SigningKey.generate()` के साथ हस्ताक्षर कुंजी बनाने के लिए
एन्ट्रॉपी के कुछ रूप की आवश्यकता होती है (इसके विपरीत
`from_secret_exponent`/`from_string`/`from_der`/`from_pem`,
जो नियतात्मक हैं और उन्हें किसी एन्ट्रॉपी स्रोत की आवश्यकता नहीं होती)। डिफ़ॉल्ट
स्रोत `os.urandom()` है, लेकिन आप `os.urandom` जैसा व्यवहार करने वाला कोई भी अन्य फ़ंक्शन
`entropy=` तर्क के रूप में पास करके कुछ अलग कर सकते हैं। यह
यूनिट टेस्ट में उपयोगी हो सकता है, जहाँ आप दोहराने योग्य परिणाम प्राप्त करना चाहते हैं।
`ecdsa.util.PRNG` उपयोगिता यहाँ काम आती है: यह एक सीड लेती है और एक मजबूत
छद्म-यादृच्छिक स्ट्रीम उत्पन्न करती है:```python
from ecdsa.util import PRNG
from ecdsa import SigningKey
rng1 = PRNG(b"seed")
sk1 = SigningKey.generate(entropy=rng1)
rng2 = PRNG(b"seed")
sk2 = SigningKey.generate(entropy=rng2)
# sk1 and sk2 are the same key
इसी तरह, ECDSA हस्ताक्षर निर्माण के लिए एक यादृच्छिक संख्या की आवश्यकता होती है, और प्रत्येक
हस्ताक्षर को एक अलग संख्या का उपयोग करना चाहिए (एक ही संख्या का दो बार उपयोग करने से
तुरंत निजी हस्ताक्षर कुंजी प्रकट हो जाएगी)। sk.sign() विधि एक
entropy= तर्क लेती है जो SigningKey.generate(entropy=) के समान व्यवहार करती है।
यदि आप .sign(data) के बजाय SigningKey.sign_deterministic(data) को कॉल करते हैं,
तो कोड एक यादृच्छिक हस्ताक्षर के बजाय एक नियतात्मक हस्ताक्षर उत्पन्न करेगा।
यह RFC6979 के एल्गोरिदम का उपयोग करके एक अद्वितीय k मान सुरक्षित रूप से उत्पन्न करता है,
जो निजी कुंजी और हस्ताक्षर किए जा रहे संदेश से व्युत्पन्न होता है। हर बार जब आप
एक ही कुंजी के साथ एक ही संदेश पर हस्ताक्षर करते हैं, तो आपको वही हस्ताक्षर मिलेगा (उसी
k का उपयोग करके)।
यह भविष्य के संस्करण में डिफ़ॉल्ट बन सकता है, क्योंकि यह एन्ट्रॉपी स्रोत की विफलताओं के प्रति संवेदनशील नहीं है।
एक NIST192p कुंजी युग्म बनाएँ और तुरंत दोनों को डिस्क पर सहेजें:```python from ecdsa import SigningKey sk = SigningKey.generate() vk = sk.verifying_key with open("private.pem", "wb") as f: f.write(sk.to_pem()) with open("public.pem", "wb") as f: f.write(vk.to_pem())
डिस्क से एक साइनिंग कुंजी लोड करें, उसका उपयोग संदेश पर हस्ताक्षर करने के लिए करें (SHA-1 का उपयोग करके), और हस्ताक्षर को डिस्क पर लिखें:```python
from ecdsa import SigningKey
with open("private.pem") as f:
sk = SigningKey.from_pem(f.read())
with open("message", "rb") as f:
message = f.read()
sig = sk.sign(message)
with open("signature", "wb") as f:
f.write(sig)
सत्यापन कुंजी, संदेश और हस्ताक्षर को डिस्क से लोड करें, और हस्ताक्षर को सत्यापित करें (SHA-1 हैश मान लें):```python from ecdsa import VerifyingKey, BadSignatureError vk = VerifyingKey.from_pem(open("public.pem").read()) with open("message", "rb") as f: message = f.read() with open("signature", "rb") as f: sig = f.read() try: vk.verify(sig, message) print "good signature" except BadSignatureError: print "BAD SIGNATURE"
एक NIST521p कुंजी जोड़ी बनाएं:```python
from ecdsa import SigningKey, NIST521p
sk = SigningKey.generate(curve=NIST521p)
vk = sk.verifying_key
मास्टर सीड से तीन स्वतंत्र हस्ताक्षर कुंजियाँ बनाएँ:```python from ecdsa import NIST192p, SigningKey from ecdsa.util import randrange_from_seed__trytryagain
def make_key_from_seed(seed, curve=NIST192p): secexp = randrange_from_seed__trytryagain(seed, curve.order) return SigningKey.from_secret_exponent(secexp, curve)
sk1 = make_key_from_seed("1:%s" % seed) sk2 = make_key_from_seed("2:%s" % seed) sk3 = make_key_from_seed("3:%s" % seed)
Load a verifying key from disk and print it using hex encoding in
uncompressed and compressed format (defined in X9.62 and SEC1 standards):```python
from ecdsa import VerifyingKey
with open("public.pem") as f:
vk = VerifyingKey.from_pem(f.read())
print("uncompressed: {0}".format(vk.to_string("uncompressed").hex()))
print("compressed: {0}".format(vk.to_string("compressed").hex()))
संपीड़ित प्रारूप से हेक्स स्ट्रिंग से एक सत्यापन कुंजी लोड करें, आउटपुट असंपीड़ित करें:```python from ecdsa import VerifyingKey, NIST256p
comp_str = '022799c0d0ee09772fdd337d4f28dc155581951d07082fb19a38aa396b67e77759' vk = VerifyingKey.from_string(bytearray.fromhex(comp_str), curve=NIST256p) print(vk.to_string("uncompressed").hex())
दूरस्थ पक्ष के साथ ECDH कुंजी विनिमय:```python
from ecdsa import ECDH, NIST256p
ecdh = ECDH(curve=NIST256p)
ecdh.generate_private_key()
local_public_key = ecdh.get_public_key()
#send `local_public_key` to remote party and receive `remote_public_key` from remote party
with open("remote_public_key.pem") as e:
remote_public_key = e.read()
ecdh.load_received_public_key_pem(remote_public_key)
secret = ecdh.generate_sharedsecret_bytes()
brainpoolP512r1secp112r1secp112r2secp128r1secp160r1