În articolul precedent, am analizat diferite metode pentru a genera o cheie privată. Indiferent de metoda pe care o alegeți, veți ajunge cu 32 de octeți de date. Iată cel pe care l-am obținut la sfârșitul acestui articol:

60cf347dbc59d31c1358c8e5cf5e45b822ab85b79cb32a9f3d98184779a9efc2

Vom folosi această cheie privată pe tot parcursul articolului pentru a obține atât o cheie publică, cât și adresa pentru portofelul Bitcoin.

Ceea ce vrem să facem este să aplicăm o serie de conversii la cheia privată pentru a obține o cheie publică și apoi o adresă de portofel. Majoritatea acestor conversii se numesc funcții hash. Aceste funcții hash sunt conversii unidirecționale care nu pot fi inversate. Nu vom merge la mecanica funcțiilor în sine – există o mulțime de articole grozave care acoperă acest lucru. În schimb, vom analiza modul în care utilizarea acestor funcții în ordinea corectă vă poate conduce la adresa portofelului Bitcoin pe care o puteți utiliza.

Criptografie pe curbă eliptică

Primul lucru pe care trebuie să-l facem este să aplicăm algoritmul de semnătură digitală ECDSA sau Elliptic Curve la cheia noastră privată. O curbă eliptică este o curbă definită de ecuație y² = x³ + ax + b cu un ales a și b. Există o întreagă familie de astfel de curbe care sunt cunoscute și utilizate pe scară largă. Bitcoin folosește secp256k1 curba. Dacă doriți să aflați mai multe despre criptografia Elliptic Curve, vă voi referi la Acest articol.

ad-banner

Prin aplicarea ECDSA la cheia privată, obținem un număr întreg de 64 de octeți. Acesta constă din două numere întregi de 32 de octeți care reprezintă X și Y ale punctului de pe curba eliptică, concatenate împreună.

Pentru exemplul nostru, avem: 1e7bcc70c72770dbb72fea022e8a6d07f814d2ebe4de9ae3f7af75bf706902a7b73ff919898c836396a6b0c96812c3213b99372050853bd1678da0ead14487d7.

În Python, ar arăta astfel:

public_key_bytes = codecs.decode(public_key, ‘hex’)
# Run SHA-256 for the public key
sha256_bpk = hashlib.sha256(public_key_bytes)
sha256_bpk_digest = sha256_bpk.digest()
# Run RIPEMD-160 for the 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’)

Notă: după cum puteți vedea din cod, înainte am folosit o metodă din ecdsa modul, am decodat cheia privată folosind codecs. Acest lucru este relevant mai mult pentru Python și mai puțin pentru algoritmul în sine, dar voi explica ce facem aici pentru a elimina o posibilă confuzie.

În Python, există cel puțin două clase care pot păstra cheile private și publice: „str” și „octeți”. Primul este un șir, iar al doilea este un tablou de octeți. Metodele criptografice din Python funcționează cu o clasă „octeți”, luându-l ca intrare și returnându-l ca rezultat.

Acum, există o mică captură: un șir, să spunem, 4f3c nu este egal cu matricea de octeți 4f3c, este egal cu matricea de octeți cu două elemente, O&lt ;. Și asta eat codecs.decmetoda odei face: convertește un șir într-o matrice de octeți. Acest lucru va fi același pentru toate manipulările criptografice pe care le vom face în acest articol.

Cheie publică

Odată ce am terminat cu ECDSA, tot ce trebuie să facem este să adăugăm octeții 0x04 la începutul cheii noastre publice. Rezultatul este o cheie publică completă Bitcoin, care este egală cu: 041e7bcc70c72770dbb72fea022e8a6d07f814d2ebe4de9ae3f7af75bf706902a7b73ff919898c836396a6b0c96812c3213b99372050853bd1678da0ead14487d7 pentru noi.

Cheie publică comprimată

Dar putem face mai bine. După cum ți-ai aminti, cheia publică este un punct (X, Y) pe curbă. Cunoaștem curba și pentru fiecare X există doar două Y care definesc punctul care se află pe acea curbă. Deci, de ce să păstrezi Y? În schimb, să păstrăm X și semnul lui Y. Mai târziu, putem trage Y din asta dacă este necesar.

Specificațiile sunt după cum urmează: luăm X din cheia publică ECDSA. Acum, adăugăm 0x02 dacă ultimul octet al lui Y este egal și octetul 0x03 dacă ultimul octet este impar.

În cazul nostru, ultimul octet este impar, așa că adăugăm 0x03 pentru a obține cheia publică comprimată: 031e7bcc70c72770dbb72fea022e8a6d07f814d2ebe4de9ae3f7af75bf706902a7. Această cheie conține aceleași informații, dar este aproape de două ori mai scurtă decât tasta necomprimată. Misto!

Anterior, software-ul de portofel folosea versiuni lungi și complete de chei publice, dar acum majoritatea a trecut la chei comprimate.

Criptarea cheii publice

De acum înainte, trebuie să facem o adresă de portofel. Indiferent de metoda de a obține cheia publică pe care o alegeți, aceasta trece prin aceeași procedură. Evident, adresele vor diferi. În acest articol, vom merge cu versiunea comprimată.

Ceea ce trebuie să facem aici este să aplicăm SHA-256 la cheia publică și apoi să aplicăm RIPEMD-160 la rezultat. Comanda este importantă.

SHA-256 și RIPEMD-160 sunt două funcții hash și, din nou, nu vom intra în detaliile modului în care funcționează. Ceea ce contează este că acum avem un număr întreg de 160 de biți, care va fi folosit pentru modificări ulterioare. Să numim asta o cheie publică criptată. Pentru exemplul nostru, cheia publică criptată este 453233600a96384bb8d73d400984117ac84d7e8b.

Cum se creeaza o adresa portofel Bitcoin dintr o cheie privata

Iată cum criptăm cheia publică în Python:

public_key_bytes = codecs.decode(public_key, ‘hex’)# Run SHA-256 for the public keysha256_bpk = hashlib.sha256(public_key_bytes)sha256_bpk_digest = sha256_bpk.digest()# Run RIPEMD-160 for the SHA-256ripemd160_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’)

Adăugarea octetului de rețea

Bitcoin are două rețele, principală și test. Rețeaua principală este rețeaua pe care toți oamenii o folosesc pentru a transfera monedele. Rețeaua de testare a fost creată – ați ghicit-o – pentru a testa noi caracteristici și software.

Vrem să generăm o adresă pentru ao utiliza pe mainnet, deci trebuie să adăugăm 0x00 octeți la cheia publică criptată. Rezultatul este 00453233600a96384bb8d73d400984117ac84d7e8b. Pentru testnet, asta ar fi 0x6f octeți.

Suma de control

Acum trebuie să calculăm suma de control a cheii noastre mainnet. Ideea sumei de control este să ne asigurăm că datele (în cazul nostru, cheia) nu au fost corupte în timpul transmiterii. Software-ul portofel ar trebui să analizeze suma de verificare și să marcheze adresa ca nevalidă dacă suma de verificare nu corespunde.

Pentru a calcula suma de control a cheii, trebuie să aplicăm SHA-256 de două ori și apoi să luăm primii 4 octeți ai rezultatului. Pentru exemplul nostru, SHA-256 dublu este 512f43c48517a75e58a7ec4c554ecd1a8f9603c891b46325006abf39c5c6b995 și, prin urmare, suma de control este 512f43c4 (rețineți că 4 octeți sunt 8 cifre hex).

1611236886 658 Cum se creeaza o adresa portofel Bitcoin dintr o cheie privata

Codul pentru calcularea unei sume de verificare a adresei este următorul:

# Double SHA256 to get checksum
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’)
checksum = sha256_2_hex[:8]

Obținerea adresei

În cele din urmă, pentru a crea o adresă, doar concatenăm cheia mainnet și suma de control. Asta o face 00453233600a96384bb8d73d400984117ac84d7e8b512f43c4 pentru exemplul nostru.

Asta e! Aceasta este adresa portofelului pentru cheia privată de la începutul articolului.

Dar s-ar putea să observați că ceva este oprit. Probabil că ați văzut o mână de adrese Bitcoin și nu arătau așa. Ei bine, motivul este că acestea sunt codificate cu Baza58. Este puțin ciudat.

Iată algoritmul pentru a converti o adresă hexagonală la adresa Base58:

def base58(address_hex):
    alphabet = ‘123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz’
    b58_string = ‘’
    # Get the number of leading zeros
    leading_zeros = len(address_hex) — len(address_hex.lstrip(‘0’))
    # Convert hex to decimal
    address_int = int(address_hex, 16)
    # Append digits to the start of string
    while address_int > 0:
        digit = address_int % 58
        digit_char = alphabet[digit]
        b58_string = digit_char + b58_string
        address_int //= 58
    # Add ‘1’ for each 2 leading zeros
    ones = leading_zeros // 2
    for one in range(ones):
        b58_string = ‘1’ + b58_string
    return b58_string

Ceea ce primim este 17JsmEygbbEUEpvt4PFtYaTeSqfb9ki1F1, o adresă de portofel Bitcoin comprimată.

1611236886 339 Cum se creeaza o adresa portofel Bitcoin dintr o cheie privata

Concluzie

Procesul de generare a cheii portofelului poate fi împărțit în patru pași:

  • crearea unei chei publice cu ECDSA
  • criptarea cheii cu SHA-256 și RIPEMD-160
  • calculând suma de control cu ​​SHA-256 dublu
  • codarea cheii cu Base58.

În funcție de forma cheii publice (completă sau comprimată), obținem adrese diferite, dar ambele sunt perfect valabile.

Iată algoritmul complet pentru cheia publică necomprimată:

1611236886 61 Cum se creeaza o adresa portofel Bitcoin dintr o cheie privata

Dacă vrei să te joci cu codul, l-am publicat pe Depozit Github.

Fac un curs despre criptomonede aici pe Routech News. Prima parte este o descriere detaliată a blockchain-ului.

De asemenea, postez gânduri aleatorii despre cripto Stare de nervozitate, deci este posibil să doriți să o verificați.