La Sicurezza dietro Bitcoin: Crittografia Asimmetrica
Crittografia a Curva Ellittica ECDSA

Questo tipo di crittografia è stato introdotto per migliorare la sicurezza della Crittografia Simmetrica la quale prevede una “falla” di sicurezza nella trasmissione del messaggio.
Ma vediamo innanzitutto cos’è la Crittografia. Per Crittografia si intende (Wikipedia):
La crittografia (dall’unione di due parole greche: κρυπτóς [kryptós] che significa «nascosto», e γραφία [graphía] che significa «scrittura») è la branca della crittologia che tratta delle «scritture nascoste», ovvero dei metodi per rendere un messaggio «offuscato» in modo da non essere comprensibile/intelligibile a persone non autorizzate a leggerlo.
Un tale messaggio si chiama comunemente crittogramma e i metodi usati sono detti tecniche di cifratura.
La Crittografia è quindi una delle tecnologie su cui Bitcoin si basa per risolvere il problema del trasferimento dell’informazione, in questo caso il trasferimento dei nostri coin, in modo che sia sicuro e non modificabile da malintenzionati.
Per dovere di cronaca in questo paragrafo è verrà affrontato il concetto di crittografia nel suo essere, spiegandone il funzionamento, ma nel protocollo Bitcoin la crittografia viene utilizzata come sistema di «Firma Digitale» e non di crittografia del messaggio, i dati delle transazioni sono infatti liberamente consultabili nella blockchain. Vediamo come:
Nella crittografia si affacciano due sistemi:
- Sistema Simmetrico
- Sistema Asimmetrico
Nella crittografia simmetrica si ha una chiave, utile per criptare un messaggio che vogliamo recapitare a qualcuno rendendolo quindi incomprensibile, e contemporaneamente, sempre con la stessa chiave, per decriptarlo, renderlo quindi comprensibile al destinatario. Chiunque sia però in possesso di tale chiave può eseguire entrambe le procedure, rendendo di fatto la trasmissione insicura. Facciamo un esempio:
Alice deve mandare un messaggio a Bob, pertanto usa la sua chiave per criptare il messaggio “posseggo 150 bitcoin” in un messaggio incomprensibile che può essere decriptato solo con la sua chiave. Alice così invia a Bob il messaggio criptato e la sua chiave privata per decriptarlo così che Bob possa leggerlo, ma che succede se il messaggio e la relativa chiave vengano intercettati da una terza persona? Come potete ben capire il limite di questo tipo di crittografia sta quindi nel sistema simmetrico in cui il potere di criptare e quello di decriptare risiede nella stessa chiave; anche il mezzo (etere, internet, ecc) in cui si propaga il messaggio diventa quindi insicuro, compromettendo l’integrità del messaggio, che rischia quindi di essere intercettato anche se il canale/mezzo sia ritenuto sufficientemente sicuro.
Nella crittografia asimmetrica la vera differenza consiste nell’adozione di due chiavi, anziché una sola, una per criptare il messaggio, ed una per decriptarlo, queste chiavi sono dette:
Chiave Privata, utilizzata per decriptare il messaggio
Chiave Pubblica, utilizzata per criptare il messaggio
Torniamo ai nostri amici:
Alice deve mandare un messaggio a Bob: “posseggo 150 bitcoin”. Per far si che solo Bob possa leggere il messaggio e nessun altro, chiede a quest’ultimo la sua chiave pubblica che Alice userà per criptare il suo messaggio. La chiave pubblica diventa quindi anche il contenitore del messaggio, nel caso del protocollo Bitcoin l’indirizzo a cui inviamo i bitcoin. Il messaggio criptato con la chiave di Bob viene a lui recapitato, ed essendo solo lui in possesso della chiave per decriptarlo (chiave privata) è di fatto l’unico che può leggerlo.
Fin qui tutto bene, re-introduciamo però il problema del mezzo di trasmissione (etere, internet, ecc): chiunque sia in “ascolto” potrebbe intercettare il messaggio che Alice sta trasmettendo a Bob. Con la cifratura asimmetrica non si può leggere il contenuto, però lo si può sostituire: In questo scenario Bob potrebbe ricevere un messaggio completamente diverso una volta decriptato con la sua chiave privata: “ciao Bob ho sostituito il messaggio, scherzetto”, potrebbe essere un esempio.
Per ovviare a questo problema viene introdotta una doppia firma:
Alice cripta il suo messaggio “posseggo 150 bitcoin” con la chiave pubblica di Bob, e contemporaneamente appone una “firma” con la propria chiave privata.
Bob una volta ricevuto il messaggio oltre a poterlo decriptare con la sua chiave privata, sarà anche sicuro della provenienza e del fatto che non sia stato sofisticato grazie alla firma apposta da Alice con la sua chiave privata.
Per vedere come avviene nello specifico questo processo introdurremo una delle caratteristiche informatiche su cui il protocollo Bitcoin basa gran parte delle sue operazioni.
Funzione di Hash
Per funzione di hash si intende una procedura che trasforma un messaggio di lunghezza arbitraria in un codice alfanumerico di lunghezza prefissata. La caratteristica principale di questo algoritmo è che è unidirezionale, ovvero è molto improbabile invertirla e quindi risalire al messaggio a cui è stato applicato, rendendolo di fatto perfetto per svariati utilizzi nella crittografia.
La funzione di hash ha delle peculiarità importanti:
- identifica un messaggio univoco, non è possibile infatti che due messaggi differenti, pur essendo simili, abbiano lo stesso valore di hash
- é deterministico, in modo che lo stesso messaggio si traduca sempre nello stesso hash
- é semplice e veloce calcolare un valore hash da un qualunque tipo di messaggio
- é unidirezionale , è altamente improbabile risalire al messaggio originale partendo dal suo hash
Per quanto riguarda l’alta improbabilità di invertire una funzione di hash aprirò un piccolo paragrafo per dare qualche numero che possa far capire quanto questa caratteristica diventi di fatto «impossibile»:
Bitcoin utilizza l’algoritmo Sha256 che, come si evince dal nome, prevede l’utilizzo di 256bit, pertanto se si volesse risalire al messaggio codificato con tale algoritmo si dovrebbe tirare ad indovinare per un numero di tentativi di 2^256. Questo numero è ridicolamente grande: il canale youtube 3Blue1Brown ha reso in maniera molto chiara a quanto corrisponda, per farlo ipotizza di avere un computer in grado di generare 4 miliardi di hash al secondo, allo stesso tempo ipotizza di avere 4 miliardi di computer come questo, a questa strana unità di computer ipotizza che Google ne abbia 1000 unità per ognuna, e di dotare ogni persona della terra (circa 7,3 miliardi) di 1000 unità di questo «server», successivamente ipotizza che vi siano 4 miliardi di copie della terra dove ogni persona sia dotata di questo server da 1000 unità di cui ognuna ha 4 miliardi di computer ognuno dei quali genera 4 miliardi di hash al secondo, non contenti immaginiamo pure 4 miliardi di galassie con 4 miliardi di copie della terra al loro interno sempre con tutti quei «server», saremmo arrivati a 2^160 tentativi ogni secondo. Ancora lontani. Non voglio dilungarmi ancora perchè i calcoli sono da mal di testa, consiglio quindi la visione del video di 3Blu1Brown, la conclusione vi lascerà con un sarcastico sorriso stampato in viso:
https://youtu.be/S9JGmA5_unY
Un’altra caratteristica è “l’effetto valanga”: la minima modifica del messaggio originale produce un hash completamente diverso dal precedente.
Vediamo come funziona:
Esistono diversi algoritmi per la funzione di hash: MD4, MD5, SHA256, ecc. Quello usato dal protocollo Bitcoin come abbiamo visto è il SHA256 (Secure Hash Algorithm, prodotto dall’NSA). Poniamo di avere il messaggio “posseggo 150 bitcoin” e di volerlo sottoporre a funzione di hash con algoritmo SHA-256bit avremo:
Hash (sha256) of “Posseggo 150 bitcoin” (0.003 seconds):60B21091CE1C747542ABCECA3317158383498C39B3E20F9D70C9E10A45915762
Come si può vedere è stata prodotta un codice alfanumerico di lunghezza prefissata di 64 caratteri (256bit) partendo da un messaggio di lunghezza arbitraria.
Testiamo l’effetto valanga:
Hash (sha256) of “Posseggo 150 bitcoins” (0.005 seconds): FB1091A964B6EDEE7FFD8CEB7B5FD3801F7F9FD02CEFF1A2BFBFC9A389D0682F
Aggiungendo una sola “s” alla parola “bitcoin” ed applicando il medesimo algoritmo viene fuori un hash completamente diverso in ogni sua parte, ecco come funziona l’effetto valanga.
(La funzione di hash con algoritmo SHA-256 è stata prodotta tramite il sito www.hashemall.com)
La Crittografia delle Chiavi
Generazione del Master Seed e della Chiave Privata
Le Chiavi del protocollo di Crittografia Asimmetrica su cui si basa Bitcoin, vengono generate a partire da un’Entropia iniziale. Per Entropia consideriamo una misura del disordine di un sistema, o più semplicemente la misura di casualità di una stringa nel nostro caso. Questa misura nel protocollo Bitcoin infatti, genera a partire da una ENT iniziale, che può essere esadecimale, binaria ecc, una stringa chiamata Seme Radice (Master Seed), il quale è in sostanza la nostra Chiave Privata.
Un Seme Radice generato da ENT (d’ora in poi la chiameremo così) si presenta in questo modo:
144e5702928d93dee7ecda99e52c22c4f351810d2dd2215a5c9aea13c9055d766d86706895c78014cef7d21d2311493b7cfc804452b048c88aef372c95289c8e
Questo è un Seed generato con il protocollo Bip39. Tale protocollo introdotto da Ian Coleman implementa un codice mnemonico o più tecnicamente una sentenza mnemonica, con cui possiamo convertire il Seme Radice in una serie di parole facili da ricordare. Ricordiamoci infatti che è grazie al Seme Radice, e quindi alla facilità con cui possiamo ricordarlo o trascriverlo, che possiamo recuperare i nostri bitcoin.
(Il Seed in esempio è stato generato usato il tool di Ian Coleman presente a questo indirizzo: https://iancoleman.io/bip39/ )
utilizzando un’Entropia Iniziale Esadecimale a 128bit che ci ha riportato 12 parole:
mule laptop slogan soap popular ritual useless gaze ball sport youth web
Ma vediamo come è rappresentato tecnicamente questo processo:
A partire da un ENT Iniziale, che può essere variabile tra i 128–256bits, si genera un seme radice fino a 64byte. Viene introdotto il concetto di checksum, una sequenza di bit agganciata alla fine dell’ENT, che serve a verificare la veridicità del pacchetto di informazioni trasmesso, in questo caso proprio l’ENT, e ne da quindi univocità di esistenza. Il Checksum è sequenziale con la proporzionalità dell’Entropia (a multipli di 32bit).
Si ha quindi:
ENT128 + CS4 = 132
Il risultato, 132, viene diviso quindi in 11 gruppi di bits, ogni gruppo ha un valore compreso tra 0 e 2047. Questa conversione genererà un numero di parole uguale al calcolo riportato:
ENT128 + CS4 = 132 / 11 = 12
Riportiamo lo schema presentato da Ian Coleman per chiarezza di informazione:
CS = ENT / 32
MS = (ENT + CS) / 11
|. ENT. | CS | ENT+CS |. MS. |
+ – – – -+ – – + – – – – + – – – +
|. 128. |. 4 |. 132. |. 12. |
|. 160. |. 5 |. 165. |. 15. |
|. 192. |. 6 |. 198. |. 18. |
|. 224. |. 7 |. 231. |. 21. |
|. 256. |. 8 |. 264. |. 24. |
Ma cosa sono i BIP?
I BIP (Bitcoin Internal Proposal) sono in questo caso dei protocolli per la generazione di Seed basati su Portafogli Deterministici.
Esistono due tipi di Portafogli Deterministici:
- Portafogli Deterministici Sequenziali o Sequential Deterministic Wallet
- Portafogli Deterministici Gerarchici o Hirarical Deterministic Wallet
I primi generano una pass-phrase che può essere incrementata con un indice e poi sottoposta chiaramente ad hash, per generare nuove chiavi private e relative pubbliche.
Tornando alla nostra Seed avremo quindi:
mule laptop slogan soap popular ritual useless gaze ball sport youth web
mule laptop slogan soap popular ritual useless gaze ball sport youth web1
mule laptop slogan soap popular ritual useless gaze ball sport youth web2
mule laptop slogan soap popular ritual useless gaze ball sport youth web3
…
mule laptop slogan soap popular ritual useless gaze ball sport youth web(n)
La funzione da riga di comando applicando l’hash esadecimale è questa:
hex(sha256(‘mule laptop slogan soap popular ritual useless gaze ball sport youth web 0’))
hex(sha256(‘mule laptop slogan soap popular ritual useless gaze ball sport youth web 1’))
hex(sha256(‘mule laptop slogan soap popular ritual useless gaze ball sport youth web 2’))
E’ chiaro capire quindi che se volessimo ripristinare un portafoglio dovremmo farlo utilizzando la passhprase ad esso collegato. Un pò scomodo ad essere sinceri.
Sono stati introdotti quindi i Portafogli Deterministici Gerarchici o Hirarical Deterministic Wallet, i quali a partire da un Seed generano una Chiave Privata Primaria o Master Private Key con la quale è possibile generare altre chiavi private e pubbliche secondo uno schema ad albero con chiavi genitrici e figlie in maniera ridondante così che ogni figlia possa essere a sua volta la madre di un’altra figlia ecc.
Con questa tipologia di portafogli è così possibile recuperare tramite una sola Pass-Phrase tutta la gerarchia delle chiavi generate dal Seed ad essa collegata, questo grazie ad un Chain Code che viene allegato ad ogni chiave (privata o pubblica che sia) che funge da istruzione a questa per la generazione delle successive. Questo non è importante solo da punto di vista pratico, ma anche dal fatto che questo protocollo consente ad esempio a un server di generare nuovi indirizzi a partire dalla tua chiave pubblica senza dover mai conoscere la tua chiave privata (es: e-commerce, webserver, ecc).
GENERAZIONE DELLA CHIAVE PUBBLICA ED INDIRIZZO BITCOIN
Chiave Privata e Chiave pubblica sono strettamente legate da un concetto matematico; nel protocollo Bitcoin per la generazioni delle chiavi, ma sopratutto per la loro interazione a senso unico, è stato scelto l’algoritmo ECDSA, ovvero la Crittografia a Curva Ellittica, capace di concatenare facilmente le due chiavi con l’obiettivo però di rendere impossibile risalire alla chiave Privata a partire da quella Pubblica, rendendo il sistema univoco è quindi possibile operare nella sicurezza informatica sfruttando la crittografia.
Usiamo il sito xxxxxxx per generare una coppia di chiavi tramite algoritmo ECDSA:
Chiave Privata:
1ab7fbb65ad768ec2a746c7369b989649eeb60c38cb432f0ad4bab1e362075c4
Chiave Pubblica:
04d9847661576bc322099777667cbe199251c6b289b47e12de22e1fdfed2a1037594b943fa657dabb376d16dd653b65ccf9210278ee97a25915f7a66cec111b54b
La Chiave Privata è stata generata a 256bit, mentre la Pubblica a 512bit.
Una Chiave Pubblica viene generata da una Chiave Privata attraverso l’algoritmo ECDSA, più precisamente utilizzando uno standard di esso, chiamato secp256k1, che data una chiave privata “k”, genera la relativa chiave pubblica “K”, moltiplicando la prima per un numero che deriva da un punto specifico della curva ellittica, espresso in “x,y”, chiamato G (generator point):
K = k * G
Generazione di un indirizzo Bitcoin
L’indirizzo Bitcoin, come abbiamo visto, è il contenitore dei nostri bitcoin, ed è quello che noi forniamo a chi deve inviarci una somma di denaro digitale. Questo indirizzo è generato a partire dalla chiave pubblica, anch’esso in maniera asimmetrica, possiamo quindi rilevare come il processo parti dalla generazione della chiave privata da entropia, dalla quale deriva per algoritmo ECDSA la relativa chiave pubblica e, da quest’ultima, viene generato un indirizzo bitcoin, il tutto in maniera unidirezionale, è impossibile infatti risalire “controcorrente” a causa dell’univocità dei mezzi matematici usati per questi processi.
Per generare un indirizzo Bitcoin ricorriamo ancora una volta alla funzione di Hash, che in questo caso prevede due funzioni principali più una terza:
- SHA256
- RIPEMD160
Dunque avremo una funzione di questo tipo:
Ripmed160(Sha256(K)) = Indirizzo Bitcoin
Dove K è la nostra chiave pubblica.
A questo punto applicheremo una terza funzione chiamata “Base58Check”.
Le prime due funzioni svolgono un “double hash” sulla chiave pubblica K generando un hash a 160bits che verrà successivamente codificato dalla funzione Base58Check che è fondamentale per rappresentare con valori alfanumerici l’hash generato; si tratta di una funzione molto importante perchè permette, oltre a rappresentare l’indirizzo, anche a prevenire errori di lettura e trascrizione: il Base58 è come il più comune Base64 utilizzato per rappresentare i caratteri delle email, ma a differenza di quest’ultimo sono stati eliminati tutti quei caratteri che possono generare errori di trascrizione come lo “0”, la “O”, la “l”, la “I”, facilmente scambiabili l’uno con l’altro.
Inoltre questa funzione applica un “checksum” composto da 4 bytes generato da un doppio Sha256 applicato nella precedente funzione e che aumenta ulteriormente la sicurezza da errori: il software infatti in fase di decodifica calcola il checksum dei dati e lo confronta con quello incluso nel codice. I due devono corrispondere necessariamente, in caso contrario rifiuta l’indirizzo Bitcoin, prevenendo il wallet, ad esempio, dall’accettare indirizzi non validi ed inviargli quindi dei fondi che andrebbero inevitabilmente persi.
Ringraziamenti:
Ringrazio Alberto Alì per aver menzionato questo lavoro nella sua tesi di laurea triennale in Informatica e per avermi a sua volta citato nei ringraziamenti della stessa.
Ringrazio Emanuele Laface e Andrea Bortolato della Community di Crypto Italia per avermi fatto notare degli errori e delle inesattezze che sono state poi corrette grazie al loro intervento.