Recupero ultima parola della Seed Phrase

Seed Phrase recupero ultima parola

# blocco: 838454

Indice

È una giornata come tante quando all’improvviso decidi di controllare la tua seed phrase riposta nel luogo più sicuro della casa. All’improvviso, un brivido ti scuote la schiena: l’ultima parola della seed phrase è misteriosamente scomparsa!

Seed Phrase senza ultima parola

Il panico prende il sopravvento. La tua mente comincia a correre veloce, cercando di immaginare come sia potuto accadere.

Inizi a considerare ogni possibilità. Potresti averla accidentalmente cancellata, o forse è stata mangiata da un insolito insetto. Le teorie più strane iniziano a sfilare nella tua mente mentre il tempo scorre implacabile.

Il solo pensiero di perdere per sempre i tuoi Bitcoin ti fa contorcere lo stomaco.

Inizi a raccogliere forze e idee e decidi di affrontare la situazione con calma e ingegno.

Ti ricordi che la seed phrase del tuo wallet è stata creata con lo standard BIP39 che prevede la combinazione di 2048 parole.

Ottimo!!! Ti manca solo l’ultima delle 24 (o 12) parole della tua seed phrase…devi al massimo fare 2048 tentativi per ripristinare il tuo wallet!!! Una speranza inizia ad accendersi in te e sudori freddi iniziano a sparire 🙂

All’improvviso hai un’altra illuminazione: l’ultima parola della seed phrase è speciale e dipende dalle parole precedenti!!! Il numero di tentativi per ripristinare il wallet potrebbe calare drasticamente.

Ma come calcolarla?

Serve qualcosa che automatizzi la procedura e che calcoli tutte le possibili combinazioni valide.

Python e qualche semplice riga di codice fanno al caso tuo!!!!

Predisposizioni software

Prima di cominciare, è essenziale assicurarsi di avere tutto il necessario installato: Python e Visual Studio Code.

Se non sei sicuro da dove iniziare, niente paura. Questo articolo del blog Come installare Python 3.0 ti guiderà passo dopo passo nell’installazione e nella configurazione di Python e Visual Studio Code.

La libreria Hashlib

Per i nostri scopi abbiamo la necessità di installare la libreria Python Hashlib.

La libreria hashlib di Python è un modulo che fornisce un’interfaccia unificata per vari algoritmi di hash crittografici.

Per chi non lo sapesse, gli algoritmi di hash crittografici sono utilizzati per generare “hash” o “digest” univoci di dati, che sono rappresentazioni fisse delle informazioni di input. Questi hash sono spesso utilizzati per garantire l’integrità dei dati e la loro autenticità.

In pratica, l’hashing converte i dati in ingresso, come una stringa, un file o un oggetto, in una stringa di byte di dimensioni fisse. L’hash o digest rappresenta l’input in modo unico e riproducibile.

La libreria hashlib include implementazioni di algoritmi comuni come SHA-1 (Secure Hash Algorithm 1), SHA-224, SHA-256, SHA-384, SHA-512, SHA-3, e MD5 (Message Digest Algorithm 5), tra gli altri.

Senza dover inventare l’acqua calda, sfrutteremo questa libreria per utilizzare l’algoritmo SHA-256 e convertire una stringa d’ingresso in una stringa di 256 bit.

La libreria hashlib è presente di default dalle versioni 2.5 di Python. Non dovremmo fare quindi nessuno sforzo per aggiungerla.

Sviluppo del programma Python

Siamo pronti ad iniziare a scrivere il nostro programmino Python che chiameremo con un nome super fantasioso: FindThePhrase.

Creiamo, nel posto che più vi aggrada, la cartella di lavoro FindThePhrase (ovvio che potete usare tutti i nomi che più vi piacciono).

Colleghiamoci al sito https://github.com/bitcoin/bips/blob/master/bip-0039/english.txt e scarichiamo il file english.txt contente la lista delle 2048 possibili parole con cui la seed phrase può essere composta. Salvate poi il file all’interno della cartella FindThePhrase. A breve ci tornerà utile.

Apriamo Visual Studio Code, e come visto nell’apposita guida, creiamo un nuovo file dal nome FindThePhrase.py

Per prima cosa dobbiamo far sapere al nostro codice che in inseguito utilizzeremo delle funzioni presenti all’interno della libreria hashlib:

1  import hashlib
2

All’interno della variabile seed_phrase salviamo la nostra seed phrase priva dell’ultima parola mancante che indicheremo con un bel punto di domanda ?

3  #seed phrase separata da spazi
4  seed_phrase = "hobby spend slam element elder liar lucky speak insane vital vehicle thunder appear dune despair steak lunar develop letter useless spoil top fan ?"
5  

Convertiamo la seed_phrase in una lista.

In Python, una lista è una struttura dati che permette di organizzare una sequenza ordinata di elementi; nel nostro caso, la lista sarà composta dalle parole della seed phrase. L’impiego di liste semplifica notevolmente la manipolazione e la gestione dei dati al loro interno.

Il comando split(” “) consente di aggiungere ogni parola alla lista, separandole quando viene individuato uno spazio. Questo processo fornisce un modo efficace per lavorare con le singole parole della seed phrase in modo organizzato e accessibile.

6  #converto la stringa in una lista
7  seed_phrase_list = seed_phrase.split(" ")
8  print("Seed Phrase senza l'ultima parola: ")
9  print(seed_phrase_list)
10   

attraverso la funzione print possiamo visualizzare il risultato ottenuto finora, premiamo il run and debug per avviare il nostro programma:

Seed Phrase senza l'ultima parola

Ora dobbiamo creare una seconda lista contenente le 2048 parole. La lista che creeremo prenderà le parole direttamente dal file english.txt. Tramite il comando open apriamo e il file

11  #apro il file english.txt
12  english = open("english.txt")  

e una volta aperto creiamo la nostra lista.

In questo contesto, il comando split("\\n") consente di aggiungere alla lista ogni parola separata da un carattere di nuova riga.

13  #leggo il file e lo trasformo in una lista
14  word_list = english.read().split("\n")  

Concludiamo il processo chiudendo il file mediante la funzione close.

15  #chiudo il file
16  english.close()
17   

Le prossime righe di codice convertono la seed phrase in una lista di indici associati alla word_list.

18  #converte la seed phrase nell'indice della word_list
19  seed_phrase_index = []
20  for word in seed_phrase_list:
21      if(word != "?"):
22          index = word_list.index(word)
23          seed_phrase_index.append(index)
24      else:
25          seed_phrase_index.append(word)
26  print("Indice parole della Seed Phrase: ")
27  print(seed_phrase_index)
28   

In pratica, il codice prende la “seed_phrase_list” come input e assegna a ogni parola un numero che indica la sua posizione nella lista di parole “word_list”.

Se una parola è marcata con il carattere “?”, il risultato corrispondente nell’output rimane “?”.

Alla fine, otterremo una lista di questi indici, più il carattere “?” che rappresentano le posizioni delle parole della “seed_phrase_list” nella “word_list”. Il risultato sul terminale risulta:

Indice della Seed Phrase

Nel passo successivo, il codice prende ogni numero presente nella lista degli indici e lo converte in una rappresentazione binaria a 11 bit utilizzando la funzione format(number, “011b”). L’ultima parola marcata con il carattere “?” resterà invariata.

29  #converte l'indice in binario
30  seed_phrase_binary = []
31  for number in seed_phrase_index:
32      if(number != "?"):
33          seed_phrase_binary.append(format(number, "011b"))
34      else:
35          seed_phrase_binary.append(number)
36  print("Indice convertito in binario a 11 bit: ")
37  print(seed_phrase_binary)
38   

Il risultato ottenuto sarà:

Rappresentazione binaria a 11 bit della Seed-Phrase

Se combiniamo tutti i bit appena ottenuti otteniamo un totale di 253 bits (23 parole x 11 bits ciascuna). Mancano quindi all’appello 3 bits per poter dare in pasto la seed phrase alla funzione SHA-256. La conferma ci viene data anche da queste righe di codice:

39  #calcolo del numero di bits mancanti
40  num_missing_bits = int(11-(1/3)*(len(seed_phrase_list)))
41  print("Numero bits mancanti: " + str(num_missing_bits))
42   

Il risultato è infatti:

Numero bits mancanti

I 3 bit mancanti possono essere impostati in qualsiasi modo, ossia possono essere tutti 1, tutti 0 o una combinazione di 1 e 0. In altre parole, ci sono varie permutazioni possibili per completare il totale di 256 bit richiesti. Il codice per calcolare le possibili permutazioni è il seguente:

43  #calcolo di tutte le permutazione possibili dei bit mancanti
44  missing_bits_possibile = []
45  for x in range (2**num_missing_bits):
46      missing_bits_possibile.append(bin(x)[2:].rjust(num_missing_bits, "0"))
47  print("Permutazioni possibili dei " + str(num_missing_bits) + " bits mancanti")
48  print(missing_bits_possibile)
49  

Il ciclo for x in range(2**num_missing_bits) genera tutti i numeri da 0 a 2^num_missing_bits – 1. Per ciascun numero x, la rappresentazione binaria di x viene ottenuta con bin(x).

Successivamente, la funzione rjust aggiunge il carattere di riempimento 0 a sinistra fino a raggiungere una lunghezza specificata pari a num_missing_bits. Quello che si ottiene è una lista formata dalle 8 combinazioni possibili dei 3 bits mancanti.

Permutazioni possibili dei 3 bits mancanti

Ora dobbiamo combinare i precedenti 253 bit con tutte le possibili permutazioni dei 3 bits calcolati sopra:

50  #combina la rappresentazione binaria della seed phrase con ogni possibile bit mancante per ottenere la possibile entropia
51  entropy_possible = []
52  for bits in missing_bits_possibile:
53      entropy_possible.append("".join(seed_phrase_binary[:-1])+bits)
54  print("Rappresentazione binaria della seed phrase con ogni possibile                           combinazione di " + str(num_missing_bits) + " bits mancanti")
55  print(entropy_possible)
56  

otteniamo così tutte le possibili entropie:

Entropia

Abbiamo così ottenuto le 8 possibili combinazioni a 256 bits della seed phrase da poter inserire come input alla funzione di SHA-256.

Le prossime righe di codice sono il cuore pulsante del nostro programma per il recupero della seed phrase.

57  #calcolo checksum con la funzione SHA256 della libreria hashlib
58  checksum = []
59  for entropy in entropy_possible:
60      entropy_int = int(entropy, 2)
61      entropy_bytes = entropy_int.to_bytes(len(entropy) // 8, byteorder="big")
62      sha256_hash = hashlib.sha256(entropy_bytes).digest()
63      checksum_bits = format(sha256_hash[0], "08b")
64      checksum.append(checksum_bits[:11 - num_missing_bits])
65  print("Calcolo della checksum dalle possibili combinazioni precedenti: ")
66  print(checksum)
67  

Approfondiamo ogni singolo passaggio.

Per prima cosa, convertiamo ogni singola entropia in un numero intero (entropy_int). La funzione int() accetta la stringa binaria (entropy) e la base (2), convertendo così la rappresentazione binaria in un numero intero.

Il numero intero ottenuto (entropy_int) viene convertito in un array di byte (entropy_bytes) utilizzando il metodo to_bytes(). La lunghezza dell’array di byte è determinata dalla divisione della lunghezza dell’entropia per 8 (len(entropy) // 8). Il parametro byteorder="big" specifica che l’ordine dei byte deve essere big-endian, cioè dal byte più significativo al meno significativo.

Utilizzando la libreria hashlib, il codice calcola l’hash SHA-256 dell’array di byte entropy_bytes attraverso il metodo sha256(). Il risultato viene ottenuto utilizzando il metodo digest().

Il codice estrae il primo byte dell’hash SHA-256 (sha256_hash[0]) e lo converte in una rappresentazione binaria a 8 bit utilizzando la funzione format().

Infine, il codice seleziona i primi bits necessari per ottenere la lunghezza desiderata del checksum (11 bits) utilizzando la sintassi di slicing ([:11 - num_missing_bits]) e aggiunge questa rappresentazione binaria alla lista checksum.

Il risultato è una lista di checksum calcolati per ogni possibile combinazione di bits mancanti, utilizzando l’algoritmo SHA-256 per garantire l’integrità e la sicurezza della rappresentazione binaria della “seed phrase”

Calcolo della checksum

Ora dobbiamo combinare le combinazioni a 8 bits calcolate con i corrispondenti 3 bits mancanti:

68  #combino i bits mancanti con il suo corrispondente checksum
69  last_word_bits = []
70  for missing_bits, checksum_bit in zip(missing_bits_possibile, checksum):
71     combined_bits = missing_bits + checksum_bit
72      last_word_bits.append(combined_bits)
73  print("Combinazione dei bits mancanti con il corrispondente checksum: ")
74  print(last_word_bits)
75  

In poche parole il codice combina ogni elemento della lista missing_bits_possible con il corrispondente elemento della lista checksum, ottenendo così

Combinazione dei bits mancanti con il corrispondente checksum

Ormai ci siamo, non ci resta che scoprire che parole si nascondono dietro a questa sequenza di bits. Per farlo scriviamo le seguenti righe di codice:

76  #trasformo nella corrispondente parola
77  last_word = []
78  for bits in last_word_bits:
79      last_word.append(word_list[int(bits, 2)])
80  print("Parole corrispondenti alle combinazione precedenti: ")
81  print(last_word)
82  

Il codice trasforma ogni numero binario della lista in un intero int(bits, 2).

Il numero intero altro non corrisponde che all’indice delle parola della lista word_list (word_list[int(bits, 2)]).

L’ultima parola della nostra seed phrase si nasconde tra una di queste 8 parole. Provare per credere 🙂

Parola corrispondente al binario calcolato

Per concludere, creiamo un file di txt con tutte le possibili combinazioni della Seed Phrase.

83  #scrivo le possibili combinazioni su un file txt
84  file = open("seedphrase.txt", "w")
85  index = seed_phrase_list.index("?")
86  for word in last_word:
87      seed_phrase_list[index] = word
88      for item in seed_phrase_list:
89          file.write(item+" ")
90      file.write("\n")
91  file.close()
92  print("Le possibili Seed Phrase di ripristino sono state salvate sul file seedphrase.txt")
93  

Il risultato finale lo troverete comodamente salvato sulla vostra cartella di lavoro 🙂

Trovate il progetto completo nella seguente repository GitHub:

https://github.com/Coindipity/Find-The-Phrase.git

Conclusioni

Ora che avete recuperato l’ultima parola, assicuratevi di salvare la vostra Seed Phrase con la massima sicurezza possibile, al fine di evitare eventuali inconvenienti futuri.

La perdita di più di una parola potrebbe comportare la perdita irreversibile dei vostri preziosi Bitcoin.

Fonti e approfondimenti

Condividi questo post

Altri articoli

Se apprezzi il lavoro che facciamo puoi aiutarci a mantenere i contenuti sempre di più aggiornati donandoci qualche Satoshi

CONTATTACI

Compila il form per qualsiasi richiesta di assitenza.