كيفية إنشاء عنوان محفظة Bitcoin من مفتاح خاص

في المقالة السابقة ، نظرنا في طرق مختلفة لإنشاء مفتاح خاص. مهما كانت الطريقة التي تختارها ، ستنتهي بـ 32 بايت من البيانات. إليكم تلك التي وصلنا إليها في نهاية هذا المقال:

60cf347dbc59d31c1358c8e5cf5e45b822ab85b79cb32a9f3d98184779a9efc2

سنستخدم هذا المفتاح الخاص في جميع أنحاء المقالة لاستخلاص كل من المفتاح العام وعنوان محفظة Bitcoin.

ما نريد القيام به هو تطبيق سلسلة من التحويلات على المفتاح الخاص للحصول على مفتاح عمومي ثم عنوان محفظة. معظم هذه التحويلات تسمى وظائف التجزئة. دالات التجزئة هذه هي تحويلات أحادية الاتجاه لا يمكن عكسها. لن نذهب إلى آليات الوظائف نفسها - هناك الكثير من المقالات الرائعة التي تغطي ذلك. بدلاً من ذلك ، سننظر في كيفية استخدام هذه الوظائف بالترتيب الصحيح الذي يمكن أن يقودك إلى عنوان محفظة Bitcoin الذي يمكنك استخدامه.

الاهليلجيه منحنى التشفير

أول شيء يتعين علينا القيام به هو تطبيق خوارزمية التوقيع الرقمي ECDSA أو Elliptic Curve على مفتاحنا الخاص. المنحنى الإهليلجي هو منحنى معرفة بالمعادلة y² = x³ + ax + b مع a و b المختارين. هناك عائلة كاملة من هذه المنحنيات المعروفة والمستخدمة على نطاق واسع. تستخدم Bitcoin منحنى secp256k1. إذا كنت ترغب في معرفة المزيد حول تشفير Elliptic Curve ، فسأحيلك إلى هذه المقالة.

بتطبيق ECDSA على المفتاح الخاص ، نحصل على عدد صحيح 64 بايت. يتكون هذا من عددين صحيحين 32 بايت يمثلان X و Y للنقطة على المنحنى الإهليلجي ، متسلسلين معًا.

على سبيل المثال ، حصلنا على: 1e7bcc70c72770dbb72fea022e8a6d07f814d2ebe4de9ae3f7af75bf706902a7b73ff919898c836396a6b0c96812c3213b99372050853bd1678da0ead.

في بيثون ، يبدو مثل هذا:

private_key_bytes = codecs.decode (private_key ، 'hex')
# احصل على المفتاح العمومي ECDSA
key = ecdsa.SigningKey.from_string (private_key_bytes، curve = ecdsa.SECP256k1) .verifying_key
key_bytes = key.to_string ()
key_hex = codecs.encode (key_bytes ، 'hex')

ملاحظة: كما ترون من الشفرة ، قبل أن أستخدم طريقة من وحدة ecdsa ، قمت بفك تشفير المفتاح الخاص باستخدام برامج الترميز. هذا أكثر صلة ببيثون وأقل من ذلك بالخوارزمية نفسها ، لكنني سأشرح ما الذي نفعله هنا لإزالة اللبس المحتمل.

في Python ، يوجد فصلان على الأقل يمكنهم الاحتفاظ بالمفاتيح الخاصة والعامة: "str" ​​و "bytes". الأول عبارة عن سلسلة والثاني عبارة عن صفيف بايت. تعمل أساليب التشفير في Python مع فئة "بايت" ، مع الأخذها كمدخلات وإعادتها كنتيجة لذلك.

الآن ، هناك القليل من الاهتمام: السلسلة ، على سبيل المثال ، 4f3c لا تساوي صفيف البايت 4f3c ، فهي تساوي صفيف البايت مع عنصرين ، O <. وهذا ما تفعله طريقة codecs.decode: إنه يحول السلسلة إلى صفيف بايت. سيكون هذا هو نفسه بالنسبة لجميع عمليات التشفير التي نقوم بها في هذه المقالة.

المفتاح العمومي

بمجرد الانتهاء من استخدام ECDSA ، كل ما نحتاج إليه هو إضافة البايتات 0x04 في بداية المفتاح العمومي الخاص بنا. والنتيجة هي مفتاح عمومي كامل من Bitcoin ، والذي يساوي: 041e7bcc70c72770dbb72fea022e8a6d07f814d2ebe4de9ae3f7af75bf7069090aab73ff919898c836396a6b0c9687141

المفتاح العمومي المضغوط

ولكن يمكننا أن نفعل ما هو أفضل. كما قد تتذكر ، المفتاح العمومي هو نقطة (X ، Y) على المنحنى. نحن نعلم المنحنى ، ولكل X هناك فقط Ys يحددان النقطة التي تكمن في ذلك المنحنى. فلماذا تبقي Y؟ بدلاً من ذلك ، دعنا نحتفظ X وعلامة Y. لاحقًا ، يمكننا استخلاص Y من ذلك إذا لزم الأمر.

التفاصيل هي كما يلي: نحن نأخذ X من المفتاح العمومي ECDSA. الآن ، نضيف 0x02 إذا كانت البايتة الأخيرة من Y متساوية ، والبايتة 0x03 إذا كانت البايتة الأخيرة غريبة.

في حالتنا ، البايت الأخير غريب ، لذا نضيف 0x03 للحصول على المفتاح العمومي المضغوط: 031e7bcc70c72770dbb72fea022e8a6d07f814d2ebe4de9ae3f7af75bf706902a7. يحتوي هذا المفتاح على نفس المعلومات ، ولكنه تقريبًا ضعف هذا المفتاح غير المضغوط. رائع!

في السابق ، كان برنامج المحفظة يستخدم إصدارات طويلة وكاملة من المفاتيح العامة ، لكن الآن تحول معظمها إلى مفاتيح مضغوطة.

تشفير المفتاح العمومي

من الآن فصاعدًا ، نحتاج إلى إنشاء عنوان محفظة. مهما كانت طريقة الحصول على المفتاح العمومي الذي تختاره ، فإنه يمر بنفس الإجراء. من الواضح أن العناوين ستختلف. في هذه المقالة ، سوف نذهب مع الإصدار المضغوط.

ما يتعين علينا القيام به هنا هو تطبيق SHA-256 على المفتاح العمومي ، ثم تطبيق RIPEMD-160 على النتيجة. الترتيب مهم.

SHA-256 و RIPEMD-160 هما وظيفتان للتجزئة ، ومرة ​​أخرى ، لن ندخل في تفاصيل كيفية عملها. ما يهم هو أنه لدينا الآن عدد صحيح 160 بت ، والذي سيتم استخدامه لمزيد من التعديلات. دعنا ندعو ذلك المفتاح العمومي المشفر. على سبيل المثال ، لدينا المفتاح العمومي المشفر هو 453233600a96384bb8d73d400984117ac84d7e8b.

إليك كيفية تشفير المفتاح العمومي في Python:

public_key_bytes = codecs.decode (public_key ، 'hex')
# تشغيل SHA-256 للمفتاح العمومي
sha256_bpk = hashlib.sha256 (public_key_bytes)
sha256_bpk_digest = sha256_bpk.digest ()
# قم بتشغيل RIPEMD-160 من أجل SHA-256
ripemd160_bpk = hashlib.new ('ripemd160')
ripemd160_bpk.update (sha256_bpk_digest)
ripemd160_bpk_digest = ripemd160_bpk.digest ()
ripemd160_bpk_hex = codecs.encode (ripemd160_bpk_digest، 'hex ’)

إضافة بايت الشبكة

يحتوي بيتكوين على شبكتين ، رئيسية واختبار. الشبكة الرئيسية هي الشبكة التي يستخدمها جميع الناس لنقل العملات المعدنية. تم إنشاء شبكة الاختبار - لقد خمنت - لاختبار الميزات والبرامج الجديدة.

نريد إنشاء عنوان لاستخدامه على الشبكة الرئيسية ، لذلك نحتاج إلى إضافة 0x00 بايت إلى المفتاح العمومي المشفر. والنتيجة هي 00453233600a96384bb8d73d400984117ac84d7e8b. بالنسبة إلى testnet ، سيكون ذلك 0x6f بايت.

اختباري

الآن نحن بحاجة لحساب المجموع الاختباري لمفتاح mainnet لدينا. فكرة المجموع الاختباري هي التأكد من أن البيانات (في حالتنا ، المفتاح) لم تكن تالفة أثناء الإرسال. يجب أن ينظر برنامج المحفظة إلى المجموع الاختباري ووضع علامة على العنوان غير صالح في حالة عدم تطابق المجموع الاختباري.

لحساب المجموع الاختباري للمفتاح ، نحتاج إلى تطبيق SHA-256 مرتين ثم أخذ أول 4 بايت من النتيجة. على سبيل المثال ، لدينا SHA-256 المزدوج هو 512f43c48517a75e58a7ec4c554ecd1a8f9603c891b46325006abf39c5c6b995 وبالتالي فإن المجموع الاختباري هو 512f43c4.

فيما يلي رمز حساب المجموع الاختباري للعنوان:

# SHA256 مزدوج للحصول على المجموع الاختباري
sha256_nbpk = hashlib.sha256 (network_bitcoin_public_key_bytes)
sha256_nbpk_digest = sha256_nbpk.digest ()
sha256_2_nbpk = hashlib.sha256 (sha256_nbpk_digest)
sha256_2_nbpk_digest = sha256_2_nbpk.digest ()
sha256_2_hex = codecs.encode (sha256_2_nbpk_digest، ‘hex’)
المجموع الاختباري = sha256_2_hex [: 8]

الحصول على العنوان

أخيرًا ، لإعطاء عنوان ، نحن فقط نسلسل مفتاح mainnet واختباري. هذا يجعلها 00453233600a96384bb8d73d400984117ac84d7e8b512f43c4 على سبيل المثال لدينا.

هذا هو! هذا هو عنوان المحفظة للمفتاح الخاص في بداية المقال.

لكن قد تلاحظ أن هناك شيء ما مطفأ. من المحتمل أن تكون قد شاهدت عددًا قليلًا من عناوين Bitcoin ولم يبدو الأمر كذلك. حسنًا ، السبب هو أنها مشفرة باستخدام Base58. إنه غريب بعض الشيء.

إليك الخوارزمية لتحويل عنوان سداسي عشرية إلى عنوان Base58:

def base58 (address_hex):
    الأبجدية = 45 123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz ’
    b58_string = ‘’
    # الحصول على عدد من الأصفار الرائدة
    Lead_zeros = len (address_hex) - len (address_hex.lstrip (‘0 '))
    # تحويل عرافة إلى عشري
    address_int = int (address_hex ، 16)
    # إلحاق الأرقام إلى بداية السلسلة
    بينما address_int> 0:
        رقم = address_int٪ 58
        digit_char = الأبجدية [أرقام]
        b58_string = digit_char + b58_string
        address_int // = 58
    # أضف "1" لكل 2 أصفار بادئة
    منها = Lead_zeros // 2
    لشخص واحد في النطاق (منها):
        b58_string = ‘1’ + b58_string
    عودة b58_string

ما نحصل عليه هو 17JsmEygbbEUEpvt4PFtYaTeSqfb9ki1F1 ، وهو عنوان محفظة Bitcoin مضغوط.

خاتمة

يمكن تقسيم عملية إنشاء مفتاح المحفظة إلى أربع خطوات:

  • إنشاء مفتاح عمومي باستخدام ECDSA
  • تشفير المفتاح باستخدام SHA-256 و RIPEMD-160
  • حساب المجموع الاختباري باستخدام SHA-256 مزدوج
  • ترميز المفتاح مع Base58.

بناءً على شكل المفتاح العمومي (كامل أو مضغوط) ، نحصل على عناوين مختلفة ، لكن كلاهما صالح تمامًا.

إليك الخوارزمية الكاملة للمفتاح العمومي غير المضغوط:

إذا كنت ترغب في اللعب باستخدام الكود ، فقد قمت بنشره إلى مستودع جيثب.

أقوم بإجراء دورة حول العملات المشفرة هنا على المتوسط. الجزء الأول هو وصف مفصل لل blockchain.

أقوم أيضًا بنشر أفكار عشوائية حول التشفير على Twitter ، لذلك قد ترغب في التحقق من ذلك.