Come funziona la Child Key Derivation nei Wallet HD

MayBeMan
5 min readAug 23, 2020

--

Il BIP 32 è stato il primo protocollo adottato per la gestione del Seed nei portafogli deterministici gerarchici. I portafogli HD sono disponibili come portafogli hardware, mobile e desktop, alcuni di essi sono gratuiti e altri a pagamento. I più popolari sono Trezor, KeepKey, Ledger Nano S, Mycellium, Jaxx 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 portafoglio 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 base58 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³¹-1 sono utilizzati per la derivazione classica, mentre quelli da 2³¹ a 2³²-1 sono utilizzati per la derivazione hardened.

Fatte queste premesse vediamo come funziona la CKD. Immaginiamo di voler replicare questo percorso di derivazione:

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

Decodifica chiave Master
Chiave Master

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).

Derivazione chiave privata dal Parent al Child
Chain Code e Chiave privata del Child

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 in modo da dimostrare che una coppia di chiavi condivide gli stessi valori per [ depth ] [ parent fingerprint ] [ key index ] e [ Chain Code].

Chiave Pubblica Master estesa

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

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

Chiavi Child Privata e Pubblica

Calcolo del Checksum per la chiave privata “Child”:

Calcolo del Checksum per la chiave pubblica “Child”:

Codifichiamo tutto in base58:

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:

--

--

MayBeMan
MayBeMan

Written by MayBeMan

Technician specialized in the security of electronic payment systems. Crypto supporter.

No responses yet