Develop with pleasure!

福岡でCloudとかBlockchainとか。

鍵流出攻撃Dark Skippy

ハードウェアウォレットからマスターシードを流出させるDark Skippyという新しい攻撃手法が最近公開された↓

https://darkskippy.com/

悪意ある署名デバイスによる攻撃

Dark Skippyも、ハードウェアウォレットのような署名デバイスで悪意あるファームウェアが実行された場合の攻撃手法の1つ。このような状況は、

といった原因で発生する可能性がある。

ハードウェアウォレットが侵害されている状態では、これまでも以下のような種類の攻撃が実行される可能性がある。

所定のシード攻撃

署名デバイスが攻撃者が設定した所定のシードフレーズを出力する攻撃。実際にTREZORに似せた偽のウォレットで、この攻撃が確認されている↓

https://usa.kaspersky.com/blog/fake-trezor-hardware-crypto-wallet/28299/

悪意あるxpub攻撃

シードと関係のない悪意ある拡張公開鍵(xpub)=攻撃者の拡張公開鍵を提供する攻撃。シードフレーズが安全に生成されていても、資金の受け取り用のアドレスが攻撃者のものにすり替わっていて資金を盗まれる。この攻撃は、別のデバイスでシードから公開鍵への変換を検証することで検出できる。

所定のnonce攻撃

署名時に攻撃者が設定したプライベートnonceを使用する攻撃。攻撃者は署名に使用されたプライベートnonceの値を知っているので、署名データから秘密鍵を逆算できる。この攻撃は、ユーザーが資金を実際に使用する際にのみ行えるので、攻撃者はそのトランザクションがブロックに格納される前に、RBFにより置換トランザクションで資金を盗む必要がある。

nonceグリンディング攻撃

署名に使用する公開nonceにシード情報を含めることで、多数の署名済みトランザクションが集まり、その公開nonceから十分な数のbitが集まれば、シードを復元できるという攻撃。ただ、十分なbitを調整する際に必要な計算と、影響するトランザクションの順序を識別する困難さから、実行が難しいとされている。これもう少し具体的な攻撃ロジックが知りたいけど、どっかに載ってないかな?

Dark Skippy

Dark Skippyは、シードを流出させる攻撃で、悪意ある署名デバイスがシード情報をトランザクションに埋め込む形で流出させる。

一般的なウォレットでよくあるニーモニックワードは、128 bit〜256 bitのエントロピーから生成される。単語数が12個の場合、128 bitのエントロピー=16 byteのエントロピーから生成される。

Dark Skippyの攻撃の流れは↓

  1. 上記16 byteのデータ(seed)を2つに分け、それぞれを署名のnonceに組み込む。2つあるので、トランザクションインプットが2つ必要になる。2つのプライベートnonceはそれぞれ↓
    •  {r_1 = (seed\lbrack 0:9\rbrack) \cdot H(SECRET || TXID||0)}
    •  {r_2 = (seed\lbrack 9:16\rbrack || watermark-counter) \cdot H(SECRET||TXID||1)}
      SECRETは悪意あるデバイスと攻撃者が知っている秘密の値*1で、TXIDは該当トランザクションのTXID、HはSHA-256ハッシュ関数。署名の公開nonceはそれぞれ {R_1 = r_1 \cdot G, R_2 = r_2 \cdot G}。また、攻撃者がこのトランザクションを検知できるように、 {H(SECRET || R_2)}の値の先頭11 bitが0で始まるよう、watermark-counterの値をインクリメントする。
  2. 攻撃者はmempoolのトランザクションをスキャンし、 {R_2}とSECRET値のハッシュ値を計算し、それが対象のトランザクションかどうか確認する。
  3. 攻撃者は対象のトランザクションを見つけると、署名内の公開nonce  {R_1, R_2}に対して以下の計算を行う。
    •  {b_1 = H(SECRET || TXID || 0)} {b_2 = H(SECRET || TXID || 0)}を計算
    •  {D_1 = b_1^{-1}R_1}および {D_2 = b_2^{-1}R_2}を計算
  4. 3の結果、 {D_1, D_2}の値はそれぞれ↓となる。
    •  {D_1 = seed\lbrack 0:9 \rbrack \cdot G}
    •  {D_2 = (seed \lbrack 9:16 \rbrack || watermark-counter) \cdot G}
  5.  {D_1, D_2}の離散対数は9 byte(72 bit)という小さな範囲の値であるため、Pollard's Kangarooアルゴリズム(λ法)を使って*2、その離散対数を計算できる。サイトでは、256GBのRAMと32コアのマシンで90分間で解けたみたい。
  6. 5で2つのnonceの値が分かれば、それを連結してwatermark-counterの値を除外すれば、16 byteのエントロピーを構築できる。
  7. 4のエントロピーから12個のシードフレーズが復元できる。

という内容で、以下の利点が挙げられている。

  • SECRETによりブラインディングされているため、第三者トランザクションを見ても攻撃を検知できない。
  • 通常のトランザクションの署名時に実行され、Bitcoinネットワークにブロードキャストされるので、攻撃に他の通信チャネルを必要としない。
  • 少数のインプットを使用した単一のトランザクションで実行できる。

攻撃のデモコードは9月あたりに公開されるらしい

攻撃への対策

対策の大前提は、悪意あるファームウェアがデバイスにロードされないようにすること。製品を選択する際に、

  • 正規の署名済みのファームウェアのみ実行するようなセキュアブートのサポート
  • 再現可能なベンダー署名済みファームウェアビルドを提供している
  • NDAフリーなセキュアエレメントの搭載

あたりを考慮すると良さそう。もちろん正規のルートでの購入で。

また、プロトコルレベルでの緩和策がいくつか挙げられている↓

anti-exfilプロトコル

secp256k1-zkpライブラリにはanti-exfilプロトコルが実装されている。署名デバイスが独自に署名を生成できないように、ソフトウェアウォレットが外部からランダム性を追加するというもの。ただ、通信ラウンドが余分にかかるので採用しているデバイスは少ないみたい(JadeとBitBoxはサポートしてるみたい)。また、ECDSAはサポートしているけどSchnorr署名は準備中らしい。

決定性nonceの使用

多くのハードウェアウォレットでは以前からnonceを生成する際にRFC6979に従った決定性nonceの生成をサポートしている。決定性nonceが使用されていればnonceの細工はできないけど、デバイスが決定性nonceをちゃんと使用していることを確認するには、

  • 別の独立したデーバイスを使って、署名が一致することを手動で確認する必要がある
  • 悪意あるデバイスが攻撃タイミングを細工する可能性があるので、すべてのトランザクションに対してチェックする必要がある。

といった面倒な作業が必要になる。

代替案として、MuSig-DNで紹介されているような、決定性nonceが使用されていることを示すゼロ知識証明などを提供する方法も提案されている。

アダプター署名の使用

新しい緩和策として提案されているのがPTLCとかでも登場するアダプター署名を使用するようにすることで、Dark Skippyや所定のnonce攻撃を無効化する提案。ただ、nonceグリンディング攻撃は防げない。

nonceにPoWを求める

nonceグリンディング攻撃への対策として、公開nonce Rについて、SHA256(k || R)の値が0がx個続くように求めるというもの。署名に5秒かかるような設定で、それ以上に不自然に時間がかかれば、攻撃の可能性があるということ。欠点は、ユーザーやウォレットがそれに気付く必要がある点。

*1:SECRETを使用するのは、攻撃者のみがシードを抽出できるようにするため。

*2:このアルゴリズムでは、飼い慣らしたカンガルーと野生のカンガルーが群の要素をジャップして通過し、最終的に同じ経路にジャンプして衝突を見つけようとするカンガルーが登場する。そしてオーストラリアの有名なTV番組Skippy the Bush Kangarooから名前を取ってDark Skippyという名称になったらしい。