HomeBlockchainBIP 32 e i wallet HD per custodire le crypto

BIP 32 e i wallet HD per custodire le crypto

Il BIP 32 è stato il primo protocollo adottato per la gestione del seed nei wallet HD (hierarchical deterministic). I portafogli HD sono disponibili sia come portafogli hardware, che per mobile e desktop; alcuni di essi sono gratuiti e altri a pagamento. 

I più popolari sono Trezor, KeepKey, Ledger Nano S, Mycelium, Jaxx, Eidoo e Electrum. 

Questi wallet richiedono un singolo backup che consente all’utente di ripristinare completamente i dati in qualsiasi momento. 

Ciò è dovuto alla capacità del wallet di guidare tutte le chiavi private dell’albero usando il BIP 32. Si tratta di un protocollo di trasferimento che consente alle chiavi padre di creare chiavi figlio in una gerarchia. 

Questi portafogli possono essere condivisi parzialmente o interamente con sistemi diversi, scegliendo se mantenere o meno la possibilità di spendere monete. 

Il BIP32, infatti, specifica come derivare coppie di chiavi dal seme principale in una cosiddetta struttura ad albero e come costruire un portafoglio che utilizzi tale struttura. 

Il secondo vantaggio dei wallet HD è la possibilità di creare una sequenza di chiavi pubbliche senza avere accesso alle corrispondenti chiavi private. Questo permette ai wallet HD di essere utilizzati su un server non sicuro o con sola capacità di ricezione, con l’emissione di una diversa chiave pubblica per ogni transazione. 

La Child key derivation (CKD) è la funzione che deriva un numero di chiavi “Child” da una chiave “Parent”. Per evitare che queste dipendano esclusivamente dalla chiave “Parent” vengono aggiunti ulteriori 256 bit di entropia rappresentati dal “Chain Code”. 

Questo viene utilizzato per introdurre dati apparentemente casuali nel processo, in modo che non sia sufficiente l’indice per derivare altre chiavi “child”. 

La funzione di derivazione delle chiavi si basa quindi su un hash mono-direzionale che combina: 

  • Una chiave “Parent” privata o pubblica (chiave ECDSA non compressa) 
  • Un chain code (256 bit) 
  • Un indice (32 bit) 

Vengono così generate le cosiddette “Chiavi Estese”. In sostanza una chiave estesa è solo una serializzazione codificata base 58 di alcuni dati. 

Un wallet HD viene organizzato in “Account” numerati (il predefinito è “0”). 

Ognuno è composto da due catene di chiavi: una esterna che viene utilizzata per generare gli indirizzi sul quale ricevere fondi, una interna per le altre operazioni. 

Come vengono rappresentate queste catene?

Le chiavi vengono dunque “incatenate” in un percorso di derivazione. Una coppia di chiavi Privata – Pubblica condividerà gli stessi [ depth ] [ parent fingerprint ] e [ key index ] perché saranno nella medesima posizione all’interno di questo percorso. 

Nei wallet HD è stato inoltre introdotto un metodo di derivazione noto come derivazione hardened che rompe il legame tra chiave pubblica “Parent” e il chain code del “Child”. 

La derivazione hardened utilizza per la generazione del chain code figlio la chiave privata del “Parent” e non la chiave pubblica. Per una semplice distinzione tra le chiavi ottenute dalla derivazione classica e quelle ottenute dalla derivazione hardened l’insieme dei valori possibili per il [ key index ] è suddiviso in due range: 

  • i valori compresi tra 0 a 2^31-1 sono utilizzati per la derivazione classica, 
  • quelli da 2^31 a 2^32-1 sono utilizzati per la derivazione hardened. 

Come funziona la CKD

Immaginiamo di voler replicare questo percorso di derivazione. 

Decodifichiamo la chiave privata estesa principale che troviamo in “m”. 

base58-decode xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG 7XnxHrnYeSvkzY7d2bhkJ7 

0488ade4013442193e8000000047fdacbd0f1097043b78c63c20c34ef4ed9a111d980047ad16282c7ae623614 100edb2e14f9ee77d26dd93b4ecede8d16ed408ce149b6cd80b0715a2d911a0afea0a794dec 

0488ade4 [ magic ] 00 [ depth ] 00000000 [ parent fingerprint ] 00000000 [ key index ] 47fdacbd0f1097043b78c63c20c34ef4ed9a111d980047ad16282c7ae6236141 [ chain code ] 00edb2e14f9ee77d26dd93b4ecede8d16ed408ce149b6cd80b0715a2d911a0afea [ key ] 0a794dec [ checksum ] 

L’intervallo della prossima coppia di chiavi è identificato con 0H che indica un indice Hardened. La CKD per chiavi in indice hardened prevede di derivare la chiave privata “Child” utilizzando Chain code e Chiave privata del “Parent” come input di un HMAC-SHA512. 

Questo algoritmo richiede un valore Chiave (il Chain code del “Parent”) e un Testo (Chiave del “Parent” + indice del figlio). Il primo [ key index ] degli indici Hardened è 80000000. (PS: non confondere la chiave dell’algoritmo con la Chiave). 

Abbiamo a questo punto ottenuto Chain Code e chiave del Child. Il [ Magic ] sarà lo stesso, il [ depth ] è progressivo, il [ key index ] lo abbiamo spiegato. Ci rimane da derivare il [ parent fingerprint ] prima di poter calcolare il [ checksum ] finale. Il [ parent fingerprint ] corrisponde all’ HASH 160 della chiave pubblica del genitore. 

Per ottenere la chiave pubblica “Parent” in “m” abbiamo due strade: 

  • Decodifichiamo da base58 la chiave estesa xpub. 
  • Moltiplichiamo la chiave privata per il Generator Point (G = 0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798) 

Procediamo decodificando xpub dimostrando come una coppia di chiavi condivida gli stessi [ depth ] [ parent fingerprint ] [ key index ] e [ Chain Code ]

base58-decode xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD26 5TMg7usUDFdp6W1EGMcet8 

0488b21e000000000000000000873dff81c02f525623fd1fe5167eac3a55a049de3d314bb42ee227ffed37d50 80339a36013301597daef41fbe593a02cc513d0b55527ec2df1050e2e8ff49c85c2ab473b21 

0488b21e [ magic ] 00 [ depth ] 00000000 [ parent fingerprint ] 00000000 [ key index ]: 873dff81c02f525623fd1fe5167eac3a55a049de3d314bb42ee227ffed37d508 [ chain code ] 0339a36013301597daef41fbe593a02cc513d0b55527ec2df1050e2e8ff49c85c2 [ key ] ab473b21 [ checksum ] 

Calcoliamo ora l HASH160 della chiave pubblica per ottenere il [ parent fingerprint ] del Child: 

HASH160 (0339a36013301597daef41fbe593a02cc513d0b55527ec2df1050e2e8ff49c85c2) = 3442193e 1bb70916e914552172cd4e2dbc9df811 

Abbiamo le nostre chiavi “Child”. Calcoliamone il Checksum e codifichiamo Base58: 

0488ade4 (Indica chiavi private estese) 01 3442193e 80000000 47fdacbd0f1097043b78c63c20c34ef4ed9a111d98 0047ad16282c7ae6236141 00edb2e14f9ee77d26dd93b4ecede8d16ed408ce14 9b6cd80b0715a2d911a0afea 

0488b21e (Indica chiavi pubbliche estese) 01 3442193e 80000000 47fdacbd0f1097043b78c63c20c34ef4ed9a111d98 0047ad16282c7ae6236141 035a784662a4a20a65bf6aab9ae98a6c068a81c52e 4b032c0fb5400c706cfccc56 

Calcolo del Checksum per la chiave privata “Child”: 

SHA256(SHA256 0488ade4013442193e8000000047fdacbd0f1097043b78c63c20c34ef4ed9a111d980047ad16282c7ae623614 100edb2e14f9ee77d26dd93b4ecede8d16ed408ce149b6cd80b0715a2d911a0afea)) =0a794dec e084ccdfcd78d42c3c163dc8b0620eaa265ad0761b3216907195e5e7 

Calcolo del Checksum per la chiave pubblica “Child”: 

SHA256(SHA256(0488b21e013442193e8000000047fdacbd0f1097043b78c63c20c34ef4ed9a111d980047ad1 6282c7ae6236141035a784662a4a20a65bf6aab9ae98a6c068a81c52e4b032c0fb5400c706cfccc56)) =b8b9c580 d5fa9a36a29ad7ce03c33b1eb7fb3fcbc5e8b529d2bdb66832da9584 

Codifichiamo tutto in base58: 

base58-ecncode (0488ade4013442193e8000000047fdacbd0f1097043b78c63c20c34ef4ed9a111d980047ad16282c7ae62361 4100edb2e14f9ee77d26dd93b4ecede8d16ed408ce149b6cd80b0715a2d911a0afea0a794dec) 

xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7 oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7 

base58-encode (0488b21e013442193e8000000047fdacbd0f1097043b78c63c20c34ef4ed9a111d980047ad16282c7ae62361 41035a784662a4a20a65bf6aab9ae98a6c068a81c52e4b032c0fb5400c706cfccc56 b8b9c580) 

xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCd rfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw 

Fondamentalmente questa è la derivazione Hardened: la chiave privata e il chain code del genitore vengono utilizzati per derivare la chiave successiva in un indice hardened. 

Il prossimo indice nel percorso di derivazione è non-hardened: Chain m/0H/1. A differenza della derivazione hardened è possibile derivare la chiave privata del Child (e di conseguenza la corrispondente chiave pubblica) utilizzando come input della funzione CKD la chiave pubblica del Parent al posto della privata. 

I passaggi sono i medesimi. Di seguito i risultati da ottenere: 

0488ade4 02 5c1bd648 00000001 2a7857631386ba23dacac34180dd1983734e444fdb f774041578e9b6adb37c19 003c6cb8d0f6a264c91ea8b5030fadaa8e538b020f 0a387421a12de9319dc93368 b34bc442 

0488b21e 02 5c1bd648 00000001 2a7857631386ba23dacac34180dd1983734e444fdb f774041578e9b6adb37c19 03501e454bf00751f24b1b489aa925215d66af2234 e3891c3b21a52bedb3cd711c 6f6e2af7 

base58-encode (0488ade4025c1bd648000000012a7857631386ba23dacac34180dd1983734e444fdbf774041578e9b6adb37c 19003c6cb8d0f6a264c91ea8b5030fadaa8e538b020f0a387421a12de9319dc93368b34bc442

xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaX wTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs 

base58-encode (0488b21e025c1bd648000000012a7857631386ba23dacac34180dd1983734e444fdbf774041578e9b6adb37c 1903501e454bf00751f24b1b489aa925215d66af2234e3891c3b21a52bedb3cd711c6f6e2af7

xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7 SyYq527Hqck2AxYysAA7xmALppuCkwQ 

Andrea Melchiorre

RELATED ARTICLES

MOST POPULARS

GoldBrick