1. 程式人生 > >Electrum比特幣錢包的Python程式碼分析

Electrum比特幣錢包的Python程式碼分析

如果你仍然未對Python語言的強大功能感到驚訝,那麼在這部分我們將學習如何在python中開發比特幣地址或錢包。我只是想說與你的計算機通訊是多麼容易,如果你通過python和Linux作業系統,可以用它做多少有趣的專案。

在本文中,我將分析Electrum的原始碼,這是純粹用Python編寫的比特幣錢包,它應該適用於任何python 2.x,我相信即使使用python 3.x包,預設情況下,所有依賴項該軟體使用的是預設包。因此,不需要額外的軟體。

免責宣告:使用此程式碼和資訊需要你自擔風險,對於因使用修改後的程式碼而導致的任何損害,以及本文中提供的資訊,我概不負責。如果你不知道自己在做什麼,建議不要修改生成私鑰的程式碼!

瞭解程式碼

我從Github下載了最新版本的Electrum原始碼:

https://github.com/spesmilo/electrum/releases/tag/2.8.3

種子生成器檔案基本上位於lib中,它名為mnemonic.py,函式是make_seed(),它是這段程式碼:

你也可以通過內部命令從終端實際呼叫。所以,如果你安裝了Electrum,那麼它是這樣的:

electrum make_seed --nbits 125

安裝Electrum後,將為你建立125位種子,但你也可以通過另一個python檔案呼叫該助記符指令碼,並自定義它(例如生成多個,或將其與其他程式碼整合)。

我們將建立一個名為testcall.py的新檔案,我們將在其中呼叫此助記符程式碼,但它必須位於同一個lib資料夾中。它看起來像這樣:

如果我們使用python testcall.py命令從終端呼叫它:

基本上我們從mnemonic.py檔案中匯入Mnemonic類,只是將其稱為助記符。我還沒有談過類,它們位於Python語言的更高階部分,基本上它們是將函式繫結在一起的物件。這裡的make_seed()函式包含在Mnemonic類中,並通過它與其他依賴於其他函式的函式一起呼叫。它只需要1個函式就可以完成,但是像這樣使用它更優雅,更不容易出錯,因為它可以處理異常。我不是一個很好的Classes

專家,所以我就這樣吧。

Mnemonic類中,可以定義1個引數,即語言,它具有以下值:

  • None =英語
  • en =英語
  • es =西班牙語
  • zh =中文
  • ja =日語
  • pt =葡萄牙語

你可以在i18n.py檔案中看到國家/地區程式碼,但只有這些程式碼列表現在可用,在wordlist資料夾中可見。如果你建立中文種子,只需用國家程式碼替換該引數:

print Mnemonic('zh').make_seed('standard', 132, 1)

你還可以生成多種型別的種子,你可以在version.py檔案中看到:

  • standard:普通錢包。
  • segwit:支援即將推出的基於Segregated Witness softfork的比特幣地址。
  • 2fa:基於雙因素身份驗證的錢包。
  • 下一個引數是num_bits變數,它使用nbits命令從命令列呼叫,基本上只是你的種子將擁有的位數熵(建議安全性最小值為128)
  • 最後一個引數是custom_entropy,基本上只是一個整數,可以使用該整數乘以種子數,以防你的RNG不好,這將用你自定義生成的數字替換密碼的一部分,具有相同的熵大小。

因此,如果我這樣稱呼它,我選擇了一個自定義熵數,這將以這種方式生成種子,當然熵數也必須是一個祕密:

print Mnemonic('en').make_seed('standard', 132, 2349823353453453459428932342349489238)

我真的不建議使用這個程式碼,它看起來有點奇怪,我不是加密專家,但我只是不喜歡這如何將熵插入你的數字。我聽說乘數會減少熵,所以我不確定程式碼的這一部分。事實上,我將向開發者傳送關於此問題的資訊,看看他對此有何迴應。但是不用擔心,預設錢包生成不會呼叫自定義熵部分,因此如果你通過GUI在Electrum中生成錢包,或者將其保留設定為1,那麼無需擔心。

分析種子生成器

好了,現在我們知道如何生成種子,讓我們看看種子生成器究竟做了什麼。畢竟使用Electrum的所有人都必須依賴此程式碼的安全性和完整性,否則如果這些程式碼被寫得很糟糕,你可能會損失所有的錢。因此,如果我們想在Electrum中儲存大量比特幣,我們必須100%信任此程式碼。那麼讓我們分析吧。

那麼讓我們分析一下make_seed()函式,這就是動作的位置,首先我會在其中放入許多列印程式碼,以便在每一步打印出每個變數:

基本上我只是在每一步打印出每個變數。好的,我們使用python testcall.py命令從testcall.py檔案中呼叫make_seed()函式。testcall檔案是這樣的:

print Mnemonic('en').make_seed('standard', 132, 1)

只是一個標準的種子生成,它打印出來:

好吧,讓我們一步一步來。

  • 首先匯入version.py,其中檔案的程式碼是,它基本上將該standard引數轉換為01,後者將成為種子的字首。所以它將字首設定為01字串。
  • 然後bwp(每個字的位數)變數取字列表長度的log2值,我的意思是那裡有多少個單詞,在這種情況下是英文列表:english.txt。英語列表中有2048個單詞,其中log2為11。
  • 然後將num_bits除以bwp並向上舍入,轉換為整數並再次乘以bwp。我不知道為什麼這是必要的,因為它給出了相同的值,我想這只是某種預防措施。
  • 如果我們將custom_entropy保留為預設值1,則n_custom將變為0,因此不會新增額外的熵。
  • n如果沒有新增自定義熵,它仍然與num_bits輸入相同。
  • 所以基本上如果你生成一個沒有額外熵的預設錢包,那麼n變數就會成為主數,其中包含你最初通過num_bits定義的熵量。因此,在我們的情況下它保持等價,因為我們不新增任何東西。
  • 然後my_entropy將只選擇0到2的n次方之間的隨機數,其中n是同名的n,所以它將是一個很大的數字,這是種子的原型。
  • 然後我們進入while迴圈來搜尋以01開頭的隨機數,它將作為種子的校驗和。
  • 如果自定義熵為0,那麼基本上我們只需將my_entropy數加1,直到前2位變為01.實際上它的前2位是hash格式。所以發生的是它用mnemonic_encode(i)對其進行編碼,並在用mnemonic_decode(seed)對其進行解碼之後,我猜測是否可以用單詞編碼,否則會產生一些錯誤。這就是assert命令所做的,它會測試錯誤。
  • 然後它進入is_new_seed()函式,如果你現在生成一個種子,如果你以舊格式匯入舊種子然後它進入舊函式。但是我上面執行的這段程式碼進入了新功能。這就是奇蹟發生的地方。is_new_seed()函式實際位於bitcoin.py檔案中:

  • 這裡發生的事情很有意思,首先使用mnenonic.py檔案中的normalize_text()函式對種子進行規範化,我認為中文或其他奇怪的語言會被轉換成我認為的ASCII文字。所以這個功能與英文單詞列表並不多。
  • 然後就是當事情變得有趣時,它採用種子列表的HMAC-SHA512雜湊,在它的英文文字版本中基本上就是我們的情況。它檢查前兩個字元是01,因為我們稱之為標準錢包。Electrum將標準錢包定義為種子,其種子版本的HMAC-SHA512以01開頭,一個Segwit錢包,其編碼種子版本的HMAC-SHA512以02開頭等等…所以基本上迴圈增加my_entropy變數1直到在我們的例子中,它給出的使用Seed版本編碼的HMAC-SHA512的單詞列表以01開頭。在找到該數字後,它退出迴圈,並返回種子。

就是這樣,這就是Electrum生成種子的基本方式。這個種子的HMAC-SHA512總和將從01開始,你甚至可以自己檢查。所以在Linux中你可以安裝一個名為GTKHash的工具來計算雜湊值,所以讓我演示一下,我們取種子,然後新增HMAC訊息種子版本,如該函式所定義:

因此,可以看到我們是否將HMAC訊息Seed版本與種子一起新增,它為我們提供了以01開頭的512位hash,因此在這種情況下,這是與Electrum相容的有效預設種子。

當然HMAC系統是牢不可破的,特別是它的512位版本可能是量子計算機抗性的,因此沒有辦法對該系統的種子進行逆向工程。

但是有一個問題,如果我們修復十六進位制格式的前兩個字元,顯然HMAC-SHA512輸出是十六進位制格式,那麼就會失去熵。

這就是為什麼我們從132位的熵開始,因為我們丟失了大約4位的熵,因此最後的輸出只有128位的熵,這是我們想要的預設情況,使用128位的安全熵,事實上,鑑於計算機的強大功能,建議現在使用120位以上。

所以我們從132位開始,由於修復了前2個字元,我們丟失了一些位,然後我們保持128位,這在計算上是安全的。為了暴力破解這需要超級計算機通過2128種組合,這幾乎是不可能的,因為地球上沒有足夠的能量來經歷那麼多組合,事實上有些人說你甚至不能算到這個數字範圍,更不用說hash和其他記憶體密集型操作。

結論

看起來Electrum可以安全使用。它已通過我的稽核,雖然我不是加密專家,但從我研究和學習它看起來對我來說是安全的。

我仍然對custom_entropy事情持懷疑態度,我應該問一下dev究竟做了什麼,但除此之外,預設錢包生成是完美無缺的。我認為沒有後門。

畢竟成千上萬的人都使用Electrum,特別是那些持有大量的人,所以最好安全使用,而且在我看來是這樣。

我在本文中分析了它的主要種子生成程式碼。當然程式碼遠不止這些,但是我們已經知道如果你在離線計算機上使用它生成種子,它應該是安全的。現在我沒有檢視它的網路相關部分,但我相信它們是安全的。

======================================================================

分享一些以太坊、EOS、比特幣等區塊鏈相關的互動式線上程式設計實戰教程:

  • java以太坊開發教程,主要是針對java和android程式設計師進行區塊鏈以太坊開發的web3j詳解。
  • python以太坊,主要是針對python工程師使用web3.py進行區塊鏈以太坊開發的詳解。
  • php以太坊,主要是介紹使用php進行智慧合約開發互動,進行賬號建立、交易、轉賬、代幣開發以及過濾器和交易等內容。
  • 以太坊入門教程,主要介紹智慧合約與dapp應用開發,適合入門。
  • 以太坊開發進階教程,主要是介紹使用node.js、mongodb、區塊鏈、ipfs實現去中心化電商DApp實戰,適合進階。
  • C#以太坊,主要講解如何使用C#開發基於.Net的以太坊應用,包括賬戶管理、狀態與交易、智慧合約開發與互動、過濾器和交易等。
  • EOS教程,本課程幫助你快速入門EOS區塊鏈去中心化應用的開發,內容涵蓋EOS工具鏈、賬戶與錢包、發行代幣、智慧合約開發與部署、使用程式碼與智慧合約互動等核心知識點,最後綜合運用各知識點完成一個便籤DApp的開發。
  • java比特幣開發教程,本課程面向初學者,內容即涵蓋比特幣的核心概念,例如區塊鏈儲存、去中心化共識機制、金鑰與指令碼、交易與UTXO等,同時也詳細講解如何在Java程式碼中整合比特幣支援功能,例如建立地址、管理錢包、構造裸交易等,是Java工程師不可多得的比特幣開發學習課程。
  • php比特幣開發教程,本課程面向初學者,內容即涵蓋比特幣的核心概念,例如區塊鏈儲存、去中心化共識機制、金鑰與指令碼、交易與UTXO等,同時也詳細講解如何在Php程式碼中整合比特幣支援功能,例如建立地址、管理錢包、構造裸交易等,是Php工程師不可多得的比特幣開發學習課程。
  • tendermint區塊鏈開發詳解,本課程適合希望使用tendermint進行區塊鏈開發的工程師,課程內容即包括tendermint應用開發模型中的核心概念,例如ABCI介面、默克爾樹、多版本狀態庫等,也包括代幣發行等豐富的實操程式碼,是go語言工程師快速入門區塊鏈開發的最佳選擇。

匯智網原創翻譯,轉載請標明出處。這裡是原文Electrum比特幣錢包的程式碼分析