Neutrino, Good and Bad
2019年6月8日から9日にかけて、アムステルダムで Breaking Bitcoin というカンファレンスが行われました。 本コラムは、公開された動画や書きおこしをもとに、その発表内容を追いかけ、Bitcoin のセキュリティに関する取り組みの最先端を知ろうという試みです。 発表内容を日本語で、かつ実際の事例などを交えて解説することで、少しでも皆様が Bitcoin の仕組みや最新の研究について詳しくなるための一助になれることを願います。 それでは、Jimmy Song氏の「Neutrino, Good and Bad」という講演について、見ていきましょう。
SPVについて
SPV(Simplified Payment Verification)は、Bitcoin のホワイトペーパーで提案されました。マークルルートを取得することで、トランザクションの存在を確認することができます。 しかし実装面では、BIP37 になって初めて SPV を実行できるようになりました。BIP37 の特徴は、サーバー側でフィルタリングを行う必要があるということです。接続するすべてのクライアントに対し、サーバー側では必要な処理に加えてフィルタリングを行わなくてはなりません。 BIP37 を用いてウォレットを復元しようとする場合は、ウォレットが作成される前のブロックを正しく把握する必要があります。このためにはブルームフィルターを登録し、サーバーに対しフィルター済みのブロックをリクエストします。ウォレットが古い場合、フィルターの処理や、ブロックの追跡には長い時間がかかるかもしれません。 実際、SPV を使用するウォレットは多くありません。Breadwallet では異なりますが、一般的なウォレットでは殆どの場合、集中型のサーバーによって運用されています。
クライアントがブルームフィルターを作成する手順についても、軽く触れておきましょう。 まず、ブルームフィルターをサーバーに登録します。サーバーは、そのフィルターを介してブロック内のトランザクションをすべて処理する必要があります。 ブルームフィルターごと、または要求ごとにすべてを計算する必要があり、負荷が高い処理です。BIP37 を実装するデメリットの一つと言えます。 さて、サーバーがフィルター結果を得たとしましょう。このときライトクライアントは結果だけを得ることになるので、全体を知ることはできません。 ですがこの時点で、ライトクライアントから見てトランザクションがブロックに含まれていたという正しいらしい結果を得ています。トランザクションがマークルルートで確認でき、マークルルートがブロックヘッダーに存在することから、これを検証することが可能となります。
SPV: https://bitcoin.org/en/glossary/simplified-payment-verification BIP-37: https://github.com/bitcoin/bips/blob/master/bip-0037.mediawiki BIP-37 参考リンク: https://techmedia-think.hatenablog.com/entry/2016/02/12/221225 ブルームフィルター: https://ja.wikipedia.org/wiki/%E3%83%96%E3%83%AB%E3%83%BC%E3%83%A0%E3%83%95%E3%82%A3%E3%83%AB%E3%82%BF
SPVの問題
SPVにはいくつかの問題があります。
ひとつは、プライバシー漏洩です。ライトクライアントの要求を処理するという都合上、サーバーはどのようなトランザクションやアドレスに関して処理を行っているのかを知ることができます。また、トランザクションを正しく返さないという攻撃も考えられます。 サーバーはライトクライアントが欲しい情報を知っているわけですから、存在しているトランザクションを見つからなかったと返したり、嘘をつくことができます。 この場合、ライトクライアントは複数のサーバーに何度も問い合わせをしないと、嘘をつかれていることすらわかりません。 さらに問題があり、CVE-2017-12842 では、SPV証明に関して、サーバーのいずれかでトランザクションを偽造できうるという脆弱性が報告されています。
他の問題は、クライアントがサーバーに要求をするため、サーバーから見て DoS(サービス拒否攻撃)の可能性があることです。 サーバー側で実行する処理の負荷は、クライアントが登録したブルームフィルターに比例します。これにより、DoS攻撃は本質的に回避できません。
ここまで説明したように、BIP37 はサーバーとクライアントが相互に信頼できる場合を除き、現実的な実装ではありません。双方に脆弱性が残ってしまうからです。 実際、2013年以降、コアソフトウェアには含まれているにも関わらず、SPV はほとんど使われていません。
Neutrinoの提案、BIP158
Jimmy Song 氏によって Neutrinoプロトコルとして提案されている BIP158 についてみていきましょう。
まず、サーバー側が全トランザクションからデータを抽出します。 ブロック単位で計算するので、クライアント側でフィルタを登録していた BIP37 とは異なり、クライアント数、コネクション数にフィルター数が比例しないため、DoS攻撃に対し安全です。 大部分の作業はクライアントで行う必要があるので、ブロックに関するトランザクションは圧縮されてクライアントに渡されます。この圧縮データを展開し、クライアント側で必要な情報を判断、フィルターします。 ポイントは、高い圧縮率です。通常のブロックは 1.4MB ですが、一部をハッシュ化することにより、20KB 程度まで減らします。この方法では、DoS攻撃を防ぐことができるだけでなく、クライアント単位のフィルターもなくなるため、プライバシーの漏洩も回避できます。
もちろん、良いことばかりではありません。 送信されるデータ量は、従来はトランザクションあたり 80バイトから 3KB でした。これが 20KB となれば、帯域幅を従来よりも大きく占有することになります。サーバー側から送られたデータが本当に正しいかどうか、追加の検証も必要です。 さらに、送金に関しては Neutrinoプロトコルではプライバシーの漏洩を防げません。Tor や Dandelion が必要になるでしょう。サーバー側が嘘をついた場合、それを検知できないという問題も依然として残っています。
現状では、暗号資産に関してセキュリティの検討は十分ではありません。 完全に信頼できるサーバーを用意し、モバイルウォレットから利用するときはサーバーが信頼できることが前提、というサービスも数多くあります。Electrum のように必ず正しい答えが返るという前提があれば、Neutrino は必要ないでしょう。サードパーティの企業などを信じるというのも一つの考え方です。 あるいは、多くのルールを定め、より多くのユーザーを集め、仕組みを組み合わせることで信頼を積み重ねていく方法もあります。この場合、Neutrino も必要な仕組みの一つになるでしょう。複数のサーバーから応答を返し、そのうちのいくつかが悪意を持っていても検知できる仕組み、計画を立てていくことになります。
BIP158: https://github.com/bitcoin/bips/blob/master/bip-0158.mediawiki BIP158の日本語参考記事: https://techmedia-think.hatenablog.com/entry/2018/01/24/000000 詳しい解説: https://bitcoinmagazine.com/articles/neutrino-privacy-preserving-light-wallet-protocol
おわりに
より帯域幅が必要になるものの、現実的ではなかった BIP37 を改善した Neutrinoプロトコルの提案は、今後実装を検討されていくことでしょう。 Bitcoin がセキュリティ面でもさらなる発展を遂げることができれば、より利用されやすくなることが期待できますね。
記事中の表現については講演資料を筆者なりに読み解きつつ、前後で独自の解説を加えておりますが、なにぶん新しい技術に関する内容ですので、もしも間違いなどございましたらお気軽にご指摘くださいませ。(特に技術的な指摘は大歓迎です)
【寄稿者情報】
- 前回の記事はこちら
- ハードウェアウォレットからのシードの抽出