はじめに
Bech32の脆弱性が発見されました。
私はメーリングリストで知りましたが、Bech32のissueで指摘されたようです。
-
[bitcoin-dev]メーリングリスト
https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2019-November/017443.html -
Githubのissue
https://github.com/sipa/bech32/issues/51
Bech32とは
Bitcoinのアドレスは、Base58Checkを使用していましたが、使いづらい部分を修正する為に考案された「汎用的なアドレスフォーマット」です。
以前、BC2で私が使用した資料があるので、参照ください。
脆弱性
末尾がp
である場合、その直前にq
を入れてもエラーとならずにデコードされてしまうという問題です。
リファレンスコードで検証してみました。
hrp = "te"
data = [25]
str = bech32_encode(hrp, data)
print(hrp, data, '-->', str)
hrp, data = bech32_decode(str)
print(str, '-->', hrp, data)
str = 'te1eacsl9qp'
hrp, data = bech32_decode(str)
print(str, '-->', hrp, data)
検証コード結果です。
te [25] --> te1eacsl9p
te1eacsl9p --> te [25]
te1eacsl9qp --> te [25, 29]
デコードがエラーとなるべきなのですが、なりません。
te1eacslq9p
と9
の前にq
をいれると、エラーとなります。
検証コードをGoogle Colaboratory+Githubで確認できるようにしました。
※ 2019/11/11 追記
issueにあるBech32の文字列ii2134hk2xmat79tp
を見てみます。
ii2134hk2xmat79tp
青字(ii2)は、ヒューマンリーダブルパート
ピンク(1)は、セパレータ
オレンジ(34hk2xm)は、データ
紫(at79tp)は、チェックサム
今回の問題は、チェックサムの末尾がp
である場合となっています。
Bech32は、qpzry9x8gf2tvdw0s3jn54khce6mua7l
の32文字を数値に当てはめるので、末尾がp
という事は、0x01
となります。
チェックサムは、データの正当性と誤り検出を行う為のものです。
演算していき最終的に0x01
になれば、正確なデータと判断する仕組みになっています。
演算を簡単に説明すると、5bit(10進数で0~31)毎にXOR
でチェックする仕組みです。
(※:演算内容は複雑なので、コードなどを参照してください。)
チェックサムの末尾がp
、つまり0x01
となる為、直前のチェックデータが0x00
となっている必要があります。
この状態で、q
すなわち'0x00'をXOR
してもチェックデータが変わらない為、エラーとなりません。
q
を追加すると、データにチェックサムのデータが追加されていきます。(最後の0x01
は含まない)
チェックサムのデータを全部排出したあとは0x00
が追加されていきます。
ii2134hk2xmat79tp --> ii2 [17, 21, 23, 22, 10, 6, 27]
ii2134hk2xmat79tqp --> ii2 [17, 21, 23, 22, 10, 6, 27, 29]
ii2134hk2xmat79tqqp --> ii2 [17, 21, 23, 22, 10, 6, 27, 29, 11]
ii2134hk2xmat79tqqqp --> ii2 [17, 21, 23, 22, 10, 6, 27, 29, 11, 30]
ii2134hk2xmat79tqqqqp --> ii2 [17, 21, 23, 22, 10, 6, 27, 29, 11, 30, 5]
ii2134hk2xmat79tqqqqqp --> ii2 [17, 21, 23, 22, 10, 6, 27, 29, 11, 30, 5, 11]
ii2134hk2xmat79tqqqqqqp --> ii2 [17, 21, 23, 22, 10, 6, 27, 29, 11, 30, 5, 11, 0]
ii2134hk2xmat79tqqqqqqqp --> ii2 [17, 21, 23, 22, 10, 6, 27, 29, 11, 30, 5, 11, 0, 0]
さいごに
今、Bitcoinが採用している箇所については、バイト長チェックが入るので、アドレスチェックで弾かれます。
現在Bitcoinで盛り上がっている、Taprootで採用する予定となっており、問題となりそうです。
そのTaprootが採用されるタイミングか、その前に修正される模様です。
私は、Go言語のリファレンスを書いたんですが、全く気付かなかったorz
申し訳ない・・・