著名的《Mastering Bitcoin》(《精通比特幣》)一書中有段Python代碼有誤(key-to-address-ecc-example.py),這段代碼被廣為流傳。這個錯誤有極高的概率會根據(jù)一個正確的私鑰生成一個錯誤的壓縮公鑰,從而產(chǎn)生一個錯誤的比特幣收款地址,如果使用這個地址會導(dǎo)致比特幣資金丟失。這段有BUG的代碼從此書中的第一版中就已存在,最新的第二版本依舊存在這個BUG代碼,當(dāng)然,廣為流傳的中譯版本中也自然存在。 下面是那段錯誤的代碼及其修正:https://github.com/bitcoinbook/bitcoinbook/pull/483/files
BUG的產(chǎn)生是encode函數(shù)沒有保留前導(dǎo)字符零所致,下面是BUG演示,可見丟失了一個前導(dǎo)零的公鑰產(chǎn)生了一個錯誤的比特幣地址:
這其實(shí)并不是encode函數(shù)的錯,一個正常的未添加前綴字符(”02″或”03″)的壓縮公鑰長度應(yīng)該是32字節(jié)(64個字符),encode函數(shù)會將10進(jìn)制公鑰轉(zhuǎn)換成16進(jìn)制字符串的形式,一旦當(dāng)轉(zhuǎn)換后的字符串長度不足64個字符的時候(極有可能出現(xiàn)的情況),encode函數(shù)并不會自動添加前導(dǎo)字符零以確保壓縮公鑰的長度為64個字符。zfill(64)的作用就是確保公鑰為64個字符,不足的話進(jìn)行補(bǔ)零。 以上演示數(shù)據(jù)可通過著名的比特幣在線地址生成器進(jìn)行查驗(yàn):https://www.bitaddress.org
現(xiàn)已推送了一個合并請求(Pull Request)并提供了一段重現(xiàn)此BUG的代碼,詳細(xì)信息: https://github.com/bitcoinbook/bitcoinbook/pull/483