Back to Blog

安全な保管を超えて、第2部:ウォレットの暗号技術を安全に実装する

Code Auditing
2026年11月11日
23 min read
Key Insights
  • 保存された秘密鍵のコピーを読み取らなくても、秘密鍵を復元できる場合があります。

  • 6件のインシデントから、乱数の脆弱性、エントロピーの損失、署名時のノンスの欠陥が、保護された鍵の安全性をいかに損なうかが分かります。

  • 決済機関は、自社の実装が鍵の生成時に予測不可能性を、署名時に秘密性を維持していることを検証する必要があります。

Beyond Secure Storage のPart 1では、決済システム自体が持つ署名機能の悪用を検討しました。この第2部では、不正な署名に至る別の経路、すなわち攻撃者が秘密鍵を復元し、独自に署名できるようになる暗号実装上の欠陥を検討します。問いは、攻撃者は保護された秘密鍵のコピーを読み取らずに、その鍵を再構築できるのか? ということです。

セクション1では、鍵の生成、保管、署名に関するセキュリティ要件を示します。セクション2と3では、鍵生成に関する4件の事例と署名に関する2件の事例を取り上げ、実装上の誤りとその結果を説明します。セクション4では、これらの事例から設計・実装上の原則を導き、必要な性質を検証する方法を説明します。

1. 鍵のライフサイクル全体にわたるセキュリティ上の性質

鍵は生成、保管され、署名に使用されます。図に示すように、各段階で求められるセキュリティ要件は異なります。

BIP-39のニーモニックとBIP-32の鍵導出を使用する階層的決定性ウォレットでは、暗号学的に安全な乱数データがニーモニックフレーズに符号化され、シードに変換されます。そのシードを使用して、秘密鍵、公開鍵、ウォレットアドレスを導出します [1, 2]。

生成されたシードと秘密鍵は、暗号化またはハードウェアによる分離で保護する必要があります。署名時には秘密鍵を使用し、公開情報から検証可能な署名を生成します。方式によっては、安全に生成したランダムなノンス、または秘密情報から決定論的に導出したノンスも必要です。

各段階のセキュリティ要件は次のように異なります。

  1. 生成時の予測不可能性。 攻撃者が、ウォレットを制御する秘密情報を予測したり、現実的な計算量で候補を網羅したりできてはなりません。
  2. 保管時の機密性。 権限のない者が、ソフトウェア、物理インターフェース、バックアップ、ログ、リモートサービスを通じて秘密情報を読み取れてはなりません。
  3. 使用時の情報漏えい防止。 公開されて観測可能な署名が多数あっても、署名によって秘密情報の再構築に十分な情報が漏れてはなりません。

ハードウェアウォレット、セキュアエレメント、信頼できる実行環境(TEE)は、機密性を強化できます。しかし、それらが存在するだけでは、残る2つの性質は確保されません。予測可能な鍵は安全な保管場所に置いても予測可能なままであり、秘密鍵のバイト列をホストから分離しても、署名から露出する数学的な情報は利用可能なままです。そのため、攻撃者は保管されている鍵のコピーを読み取らずに、影響を受ける鍵を復元し、その鍵が管理する資産にアクセスできる可能性があります。

次の2つのセクションでは、実装がこれらの要件にどう違反するかを検討します。生成時の欠陥は鍵を予測可能にし、署名時の欠陥は公開された署名から鍵を復元可能にします。これらの事例は、セクション4で述べる実装上の原則と検証目標の基礎となります。

2. 鍵生成の欠陥:予測可能な秘密鍵

鍵の生成では、すべての段階で予測不可能性を維持しなければなりません。エントロピー源は暗号用途に適している必要があり、その内部状態は現実的な計算量で網羅できてはなりません。また、乱数バイト列からシードや秘密鍵への変換では、意図した不確実性を維持する必要があります。128ビットのセキュリティ目標を達成するには、実装上の欠陥によって秘密情報の候補空間が現実的に探索できる規模まで縮小されないことが必要です。

次の表は、生成時にこの性質が失われる4つの経路をまとめたものです。弱いライブラリの生成器、誤った乱数生成器(RNG)の接続、情報が失われる入力変換、初期状態が限られた生成器です。影響額は異なる期間を対象とした報告に基づいており、同じ日付時点で測定された合計額ではありません。

事例 対象期間 報告された影響(概算) 以下で検討する欠陥
Ill Bloom 2026年5~7月 7月13日時点の下限は約500万 USD ニーモニック生成時の弱い乱数
Coldcard 2026年7月30日以降、集計は8月14日 1.1270億 USD ファームウェア内の誤ったRNG経路
XRPH Wallet 2026年9月3日 45万 USD 予測可能で、極めて限定されたウォレット生成用の入力
Qubic Wallet 2026年10月17日–2026年10月18日 130万 USD Math.random()を使用した安全でないシード生成

2.1 Ill Bloom:ウォレットの依存ライブラリにおける弱い乱数

Ill Bloomの事例では、一部のソフトウェアウォレットが、脆弱なバージョンのcrypto-jsを使用してBIP-39のリカバリーフレーズを生成していました。このライブラリのCryptoJS.lib.WordArray.random()は、暗号学的に安全なエントロピー源からエントロピーを取得する代わりに、Math.random()で初期化される独自のMultiply-With-Carry(MWC)生成器を使用していました。この関数をセキュリティ上重要なエントロピー源として使用したウォレットは、その後のニーモニック生成と鍵導出の手順が規格に正しく従っていても、生成器の弱点を引き継いでいました [3]。

脆弱なcrypto-js v3.1.9-1の実装 [4] には、次のような特徴的なロジックが含まれています。

  random: function (nBytes) {
      var words = [];

      var r = (function (m_w) {
          var m_w = m_w;
          var m_z = 0x3ade68b1;
          var mask = 0xffffffff;

          return function () {
              m_z = (0x9069 * (m_z & 0xFFFF) + (m_z >> 0x10)) & mask;
              m_w = (0x4650 * (m_w & 0xFFFF) + (m_w >> 0x10)) & mask;
              var result = ((m_z << 0x10) + m_w) & mask;
              result /= 0x100000000;
              result += 0.5;
              return result * (Math.random() > .5 ? 1 : -1);
          }
      });

      for (var i = 0, rcache; i < nBytes; i += 4) {
          var _r = r((rcache || Math.random()) * 0x100000000);

          rcache = _r() * 0x3ade67b7;
          words.push((_r() * 0x100000000) | 0);
      }

      return new WordArray.init(words, nBytes);
  }

ここで、r()は独自のMWCベースの生成器であり、Math.random()はその状態の初期化や状態への影響に関わります。この疑似乱数生成器(PRNG)は通常のエントロピーのように見えるバイト列を生成しますが、この実装には暗号学的な予測不可能性がありませんでした。実質的な候補空間は、公称128ビットの出力では約2 USD^{39}、公称256ビットの出力では約2USD47、公称256ビットの出力では約2 USD^{47}でした [3]。

候補空間がこのように小さかったため、リカバリーフレーズの候補を再構築し、対応するウォレットアドレスを導出して、公開されているブロックチェーン上の活動と照合することが現実的に可能でした。したがって、被害者のデバイスから何も抽出せずに秘密情報を復元できました。ニーモニックの規格に従っていても、古い依存ライブラリから引き継いだ乱数の弱さは解消できませんでした。

2.2 Coldcard:コードが使用していなかったハードウェア乱数生成器

Coldcardの事例は、安全な乱数源があっても、アプリケーションが別の生成器を呼び出していれば不十分であることを示しています。このデバイスにはハードウェア乱数生成器が搭載されていましたが、ビルド時の統合ミスにより、シード生成処理のrng_get()は、代わりにMicroPythonのソフトウェア擬似乱数生成器(PRNG)であるYasmarangに解決されていました。この暗号学的に安全ではないPRNGは、デバイス固有の固定IDと限られたタイミング情報を使って初期化されていたため、初期状態は十分に予測可能で、生成されるウォレットシードの実効エントロピーが大幅に低下していました [5]。

シード生成処理では、別のYasmarang生成器の出力も混ぜ合わせていました。古いMk2/Mk3デバイスでは、この2つ目の生成器は公開された定数から開始され、エントロピーを追加していませんでした。新しいモデルではセキュアエレメントからの乱数が導入されたものの、再シード時に保持されるのは32ビットだけでした。その結果、256ビットのウォレットシードを生成していても、実効的な探索空間は大幅に縮小していました。Coinkiteは、明示した攻撃上の前提の下で、候補数をMk2/Mk3では約2 USD^{40}、Mk4/Q/Mk5では約2USD72、Mk4/Q/Mk5では約2 USD^{72}と暫定的に推定しました [6, 7]。

この弱点により、シードの復元はオフライン探索の問題となりました。攻撃者は候補シードからアドレスを導出し、公開されたブロックチェーンデータと照合できます。実際に必要な計算量はモデルと攻撃上の前提によって異なり、2 USD^{72}という推定値は、2USD40という推定値は、2 USD^{40}の場合と同程度に実行可能であることを意味しません。照合に成功すると、対応する秘密鍵が露呈します。

2.3 XRPH Wallet:鍵の探索空間を縮小させた入力形式のバグ

生成処理には、乱数の出力をウォレットAPIが期待する入力へ変換する工程も含まれます。XRPH Walletでは、その変換によって生成された入力の大部分が破棄されていました。AndroidアプリはJavaScriptのMath.random()で10進数のブロックを生成し、それらを連結した文字列をWallet.fromEntropy()に渡していました。受け取る側のコードは各文字を小さな整数のバイト値として解釈し、先頭の16位置だけを保持していました。そのうち2位置は固定の空白区切り文字だったため、結果として得られるウォレットのエントロピーに寄与したのは、変動する10進数字14桁だけでした [8]。

padlock = { A, B, C, D, E, F, G, H };     // each = 6 digits from the line above
r6 =  A.join('') + ' ' + B.join('') + ' ' + C.join('') + ' ' + D.join('')
    + ' ' + E.join('') + ' ' + F.join('') + ' ' + G.join('') + ' ' + H.join('');
r5 = Wallet.fromEntropy;
r3 = r5.bind(Wallet)(r6);                 // a 55-char STRING is passed; fromEntropy wants 16 bytes

// compute entropy be like
const input = "528875 921568 528239 ...";  // decimal blocks
const entropy = Uint8Array.from(input).slice(0, 16);
// Result: [5,2,8,8,7,5,0,9,2,1,5,6,8,0,5,2]

この変換後に到達可能なウォレット入力は、約10 USD^{14}\approx 2^{46}通りでした。これは、16バイトのエントロピーを一様に抽出した場合に想定される約2USD128通りでした。これは、16バイトのエントロピーを一様に抽出した場合に想定される約2 USD^{128}通りの空間と対照的です。この数値が表すのは、観察された変換の下で到達可能な候補数であり、Math.random()の統計的エントロピーについての暗号学的な証明ではありません。

不適切な乱数源と、API境界での表現・エンコードの誤りという2つの問題が重なりました。ウォレットはもっともらしいアドレスを生成し、有効なトランザクションに署名できるため、どちらも機能テストでは見逃され得ます。公開された調査で明らかになったのは、鍵を復元可能な探索空間の存在です。それだけで、攻撃者がどの経路で鍵を取得したかが証明されたわけではありません。

2.4 Qubic Wallet:55文字のシードを支える弱い乱数

出力文字列がどれほど長く見えても、生成器の初期状態によって、取り得るシードが制限される場合があります。Qubicはこの問題を示しています。報告されたウォレット侵害には、JavaScriptの暗号学的に安全ではないMath.random()で生成されたシードが関係していました。影響を受けた環境には、Appleのブラウザーと、JavaScriptCoreを基盤とする一部の古いiOSアプリのビルドが含まれていました [9, 10]。

脆弱な生成ロジックとその修正は、次のようにまとめられます [11]:

// Vulnerable seed generation (abridged)
seed += letters[Math.floor(Math.random() * 26)];

// Corrected approach (schematic excerpt of the fix)
crypto.getRandomValues(bytes);
if (byte < 234) seed += letters[byte % 26];

Math.random()を55回呼び出しても、独立したエントロピー源が55個得られるわけではありません。再シードと再シードの間では、PRNGは呼び出されるたびに内部状態を決定論的に進めます。呼び出し位置を固定した場合、初期シードをSSとすると、55文字からなるウォレットシード全体は、決定論的関数W=F(S)W=F(S)で表されます。SSとその呼び出し位置が分かれば、55文字すべてを再現できます。PRNGをさらに呼び出しても、エントロピーは増えません。

取り得る初期状態の範囲は、実行環境の初期化方法によって異なります。2026年10月29日に取得したJavaScriptCoreのソースのスナップショットでは、PRNGは32ビットのシードから初期化されます。そのため、呼び出し位置を固定した場合の系列は最大2 USD^{32}通りです。ここで調査したV8のソースでは64ビットのシードが使われ、同様の系列は最大2USD64通りです。ここで調査したV8のソースでは64ビットのシードが使われ、同様の系列は最大2 USD^{64}通りです。これらの上限は、調査対象の初期化経路について、呼び出し位置を固定した場合に適用されます。これらのスナップショットからは、事件で使用されたブラウザーの正確なビルドや、それらを悪用するための計算量は分かりません。修正後の実装では、代わりにcrypto.getRandomValues()を使用して暗号学的に安全な乱数を取得し、バイトを26文字に対応付ける際の偏りを避けるため、棄却サンプリング(byte < 234)を使用しています [12, 13, 14]。

3. 署名処理の欠陥:公開署名からの秘密鍵復元

鍵を安全に生成した後も、署名に使用する際には秘密に保たなければなりません。署名のたびにデータが観察者に公開され、実装上の欠陥があると、その公開データから秘密鍵を復元するのに十分な情報が得られる場合があります。ECDSAとSchnorrでは、ノンスと呼ばれる署名ごとの秘密のスカラー値を使い、公開署名に含まれる秘密鍵の寄与を隠します。

ノンスは秘密に保ち、同じ鍵で異なるメッセージに署名する際には再利用せず、方式が求める分布の要件を満たす必要があります。決定論的な導出も、これらの要件と両立します。公開鍵と署名対象のメッセージを知っているだけでは、ノンスを予測できてはなりません。

簡略化したSchnorrの関係式を例に取ります:

s=k−rd(modn),s=k-rd\pmod n,

ここで、ddは秘密鍵、kkはノンス、rrは公開情報(公開鍵やメッセージなど)から計算される公開チャレンジ値、ssは公開される署名のスカラー値、nnは部分群の位数です。rrが逆元を持つ場合、ノンスが分かれば、直ちにd=(k−s)r−1(modn)d=(k-s)r^{-1}\pmod nから秘密鍵が明らかになります。

さらに、鍵が漏れるためにノンスの全体が判明する必要はありません。複数のノンスに共通する制約や偏りによって、格子に基づく手法で鍵を復元するのに十分な情報が得られる場合があります。実行可能性は、露呈した情報と利用可能な署名によって異なります。

この表は、本節で検討する2つのノンスの不具合を区別しています。Zilliqaのノンスは一部に制約があり、SecondFiのノンスは公開データから計算可能になりました。報告された影響は、それぞれ異なる過去の報告対象期間に基づいています。

インシデント 対象期間 報告された影響(概算) 以下で検討する不具合
Zilliqa Ledger Wallet 2026年3~7月 683,130,969.66 ZIL 偏りのあるEC-Schnorr署名ノンス
SecondFi 2026年6月 引用されたコード上の証拠からは確定できない Ed25519のノンス導出の不具合

3.1 Zilliqa Ledger Wallet:すべてのSchnorrノンスで64ビットが欠落

Zilliqa Ledger Walletのインシデントは、従来のZilliqa EC-Schnorrトランザクションに使用されるアプリケーションの不具合に関係していました [15]。アプリケーションはノンスの材料を生成していましたが、その誤った部分を最終的な署名用バッファにコピーしていました。8バイトのゼロ埋めを残し、実際の乱数を8バイト破棄していたのです。その結果、影響を受けたすべてのノンスは、約256ビットのsecp256k1の群の位数全体に適切に分布する代わりに、0 USD \le k < 2^{192},$ を満たしていました。

署名の式から、ノンスの範囲が制限されることがなぜ重要なのかが分かります。

P=dG,Q=kG,r=H(compress⁡(Q)∥compress⁡(P)∥m)  n,s=k−rd(modn).\begin{aligned} P &= dG,\\ Q &= kG,\\ r &= H(\operatorname{compress}(Q)\|\operatorname{compress}(P)\|m)\bmod n,\\ s &= k-rd\pmod n. \end{aligned}

ここで、GG は群の生成元です。式を変形すると、次のようになります。

k=s+rd(modn).k=s+rd\pmod n.

したがって、各署名から、未知の dd について、ノンスが 2 USD^{192}$ で上限を定められた合同関係が得られます。独立した関係を複数組み合わせると、格子簡約によって解を求められる隠れた数の問題(HNP)の一例となります。公式の事後分析では、影響を受けた署名が4つ以上あれば秘密鍵を復元できると報告されています。

セキュアエレメントが秘密鍵のバイト列を明かす必要はありませんでした。ノンスの偏りにより、すでにオンチェーンで公開されていた署名から秘密鍵を復元できる状態になっていたのです。

3.2 SecondFi:公開データから計算可能な署名ノンス

SecondFiでは、Ed25519のノンス導出が誤っていたため、ノンスの一部が制約されるにとどまらず、公開データからノンスを計算できる状態になりました。これにより、公開されているトランザクションの署名1つから署名用の秘密鍵を復元できました [16]。

Ed25519方式の署名では、本来、秘密鍵の材料から秘密スカラー aa と秘密のノンス用プレフィックスを導出します。ここで、A=aBA=aB は公開鍵、BB はEd25519の基点、MM は署名対象のメッセージ、LL は部分群の位数、HH はSHA-512を表します。概略は次のとおりです。

r=H(secret nonce prefix∥M)  L,R=rB,h=H(R∥A∥M)  L,S=r+ha(modL).\begin{aligned} r &= H(\text{secret nonce prefix}\|M)\bmod L,\\ R &= rB,\\ h &= H(R\|A\|M)\bmod L,\\ S &= r+ha\pmod L. \end{aligned}

不具合のある実装では、代わりに r=H(M)  Lr=H(M)\bmod L としていました。署名対象のメッセージを知る人なら誰でも rr を導出できます。RR、AA、SS は公開されているため、観察者は次の計算を行えます。

a=(S−r)h−1(modL),a=(S-r)h^{-1}\pmod L,

ただし、hh が LL を法としてゼロでないことが条件です。

Zilliqaでノンスの一部が漏えいしたケースとは異なり、影響を受けた署名1つで署名用スカラーを復元するには十分でした。これは、元のニーモニックや、階層型ウォレット内のほかのすべての鍵も復元できることを自動的に証明するものではありません。不具合があったのは鍵導出と署名の接点です。必要な秘密情報は存在していましたが、ノンス導出ルーチンに渡されていませんでした。

4. 安全な実装の原則と検証

これらの事例を総合すると、乱数源や署名アルゴリズムだけでなく、それらをつなぐコードもレビューしなければならない理由が分かります。予測不能な乱数源からは予測不能な鍵が生成されなければならず、その鍵は署名時にも秘密に保たれなければなりません。変換ルーチンやライブラリのインターフェースでの誤りは、どちらの要件も損なう可能性があります。

4.1節と4.2節では、鍵生成と署名に関する設計・実装の原則を示します。4.3節では、デプロイされたシステムでそれらの原則が守られているか評価するために、レビューとテストでどのような証拠を得るべきかを説明します。

4.1 鍵生成時の安全性を維持する

鍵生成に関する事例から、実装には次の3つの要件があることが分かります。

  1. 暗号学的に安全な乱数を使用し、失敗時には処理を停止する。 シードと秘密鍵には、暗号学的に安全な擬似乱数生成器(CSPRNG)など、適切な暗号学的に安全な乱数源が必要です。Ill BloomとQubicの事例は、汎用の乱数生成器がその役割を果たせない理由を示しています。予定していた乱数源を利用できない場合や、その乱数源が失敗した場合は、弱い代替手段を黙って使用するのではなく、生成を停止しなければなりません。

  2. データ変換を通じてエントロピーを維持する。 安全な乱数源の出力は、符号化、サンプリング、インターフェース間での受け渡しを通じて、必要な不確実性を保持しなければなりません。XRPH Walletの事例は、見た目には有効な出力だけでは不十分な理由を示しています。意図しない切り詰めや偏りのある対応付けによって実効的な鍵空間が縮小しないよう、型、長さ、符号化に関する制約を設ける必要があります。

  3. デプロイされたコードが予定どおりの乱数源を使用するようにする。 Coldcardの事例が示すように、安全な乱数源が存在するだけでは、アプリケーションが実際にどの乱数源を呼び出すかは分かりません。エラー処理やフォールバックの経路を含め、統合、コンパイル、デプロイを経ても乱数源の選択が正しく維持されなければなりません。RNGに関する設計上の前提は、対象プラットフォームで動作する実行ファイルでも成り立つ必要があります。

4.2 署名時に秘密を保持する

鍵生成に関する要件は、鍵の作成方法を守るためのものです。使用中も鍵を秘密に保つには、ノンスを正しく扱う必要があります。要件は署名方式によって異なります。以下には、事例で検討したSchnorrとEd25519に加えて、ECDSAも含めます。

  1. ECDSA: ノンスの秘密性と予測不能性を保ち、異なるメッセージ間で同じ鍵の下でノンスが再利用されるのを防ぎます。RFC 6979 [17] に従う決定論的な生成では、署名のたびに新たな外部乱数を必要としませんが、実装には依然としてサイドチャネルによる漏えいや故障攻撃への対策が必要です。

  2. EdDSA: ノンス導出に必要な秘密の入力をすべて保持します。SecondFiの事例は、秘密のプレフィックスを省略し、公開データだけを使用した場合の結果を示しています。ラッパーや鍵アダプターは、署名が機能することを入力の正しさの証拠とみなすのではなく、RFC 8032 [18] で必要とされる秘密の入力を漏れなく渡さなければなりません。

  3. Schnorr: 署名方式で求められるノンスの分布と表現を維持します。Zilliqaの事例が示すように、乱数の一部が失われる場合、ノンスの繰り返しや完全に予測可能なノンスを避けるだけでは不十分です。データ処理やスカラー変換によって、悪用可能な制約や偏りが生じてはなりません。

十分にレビューされたライブラリは実装上のリスクを減らしますが、統合時の誤りをなくすわけではありません。署名の基本処理が正しくても、呼び出し元が不完全または破損した入力を渡せば、安全ではありません。

4.3 セキュリティ特性をテストする

これらの要件が満たされているか評価するには、実際に動作する実装の中で入力を追跡する必要があります。有効な出力によって統合時の誤りが隠れることもあるため、通常の機能テストでは見逃す経路も検証対象に含める必要があります。次の表は、鍵生成と署名に関する要件を具体的なレビュー目標に落とし込んだものです。

レビュー対象 検証目標
エントロピーの予測不能性 乱数源、初期化、実効的なシード空間が、現実的な予測や総当たりによる列挙に耐えられるかを確認する
エントロピーの維持 変換とサンプリングが、意図しない切り詰めや偏りを生じさせずに必要な不確実性を維持することを検証する
RNGの統合 エラー処理やフォールバックの経路を含め、デプロイされた実行ファイルが予定どおりの乱数源を使用することを確認する
ノンスの秘密性 必要な秘密の入力をすべて含め、ノンスの生成または導出で秘密性が保たれ、公開データだけからはノンスを再現できないことを検証する
ノンスの正しさ 該当する場合は既知解テストや独立した実装を用いて、ノンスの扱いを署名方式の要件と比較する
依存関係の安全性 暗号関連の依存関係のバージョンと統合方法をレビューし、更新後も必要な動作が維持されることを確認する

これらの目標を評価するには、複数の方法を組み合わせる必要があります。コードレビューでは、秘密の入力と乱数入力が、デプロイされた鍵生成・署名ルーチンにどのように届くかを追跡します。異常系のテストと故障注入では、通常の前提が成り立たない場合の動作を調べます。既知解テストや独立した実装との比較では、署名方式からの逸脱を発見できる可能性があります。統計的なテストでは明らかな偏りを検出できますが、アドレスの生成、署名の検証、統計的なテストのいずれかが成功しただけでは、暗号学的な安全性は証明できません。乱数源、入力処理、署名方式の要件に照らして、証拠を総合的に評価してください。

第三者のセキュリティチームや専門家は、特に乱数源、鍵導出、署名ライブラリが接する箇所について、コードと統合の監査を通じて内部検証を補完できます。その対象には、依存関係のバージョン、ビルド設定、実際に実行されるコードの経路を含めるべきです。監査結果では、影響を受けるセキュリティ特性を特定し、再現可能な証拠と回帰テストを提示する必要があります。実装や依存関係を変更した場合にも、検証は必要です。

Web3に最適なセキュリティ監査会社

ローンチ前に設計、コード、ビジネスロジックを検証

5. 結論

6件のインシデントから、実装上の誤りが保護された鍵の安全性を損なう2つの経路が分かります。生成時にあり得る鍵の範囲を狭めることと、署名を通じて既存の鍵に関する情報を漏らすことです。本稿では、これらの不具合の分析を鍵生成と署名の要件に落とし込み、決済インフラにデプロイされるコードのレビューとテストの目標を示しました。

決済機関にとって、安全な保管は保存された秘密情報を守るものです。予測可能な鍵生成や、署名によって漏れた情報を修復することはできません。必要なセキュリティ特性は、依存関係、アダプター、デプロイを経ても維持されなければなりません。レビューとテストでは、有効なアドレスや署名から安全性を推測するのではなく、実装全体を調べる必要があります。

これらの実装要件は、Beyond Secure Storageの第1部で検討したワークフロー上の統制を補完するものです。第1部では、ワークフロー上のリスク、予防的なチェック、そしてチェックによって不正な操作を止められなかった場合の損失抑制を検討します。第2部では、攻撃者に独立して署名する能力を与え得る実装上の不具合を扱います。暗号処理が正しく実行されたことは、業務上の承認があった証拠にはなりません。また、業務上の承認が有効であっても、署名鍵が予測不能で復元できないことの証拠にはなりません。安全な決済・署名システムには、承認ワークフローと、その基盤となる暗号実装の両方を設計し、検証することが必要です。

参考文献

Sign up for the latest updates
安全な保管を超えて、第1部:安全な決済・署名ワークフローの設計
Security Insights

安全な保管を超えて、第1部:安全な決済・署名ワークフローの設計

攻撃者が秘密鍵を盗まずに、認可されていない操作が有効な署名を得ることは、なぜ可能なのでしょうか。「安全な保管の先へ」第1回では、Bitget、Bybit、Binanceなどの事例を通じて、支払い要求、トランザクションの構築、署名、実行、決済の各段階における認可の不備を検討します。そのうえで、認可されていない操作を防ぎ、損失を抑えるための設計原則を導き出し、レビュー、監査、ペネトレーションテスト、演習によって、それらの防御策をどう検証できるかを説明します。

NEAR Intentsの悪用:返金処理の欠陥とセキュリティ上の教訓
Security Insights

NEAR Intentsの悪用:返金処理の欠陥とセキュリティ上の教訓

NEAR Intentsへの攻撃では、過大な払い戻しイベントを利用し、預け入れた資産が返還された後も内部残高を維持しました。本分析では、レシートの処理の流れと、合計3,865,021 USDTに上るBNB Chainでの7件の出金を再構成します。また、これらの資金流出とプロジェクトが報告した全額回収を区別し、NEARスマートコントラクトの開発と監査におけるセキュリティ上の考慮事項を示します。

損失約557万 USD:X100 FreezerとNEMへの攻撃 | BlockSec Weekly
Security Insights

損失約557万 USD:X100 FreezerとNEMへの攻撃 | BlockSec Weekly

本週次レポートでは、2026年10月19日–2026年10月25日にEthereumとBNB Chainで発生した2件のセキュリティインシデントを取り上げます。フラッシュローンを資金源としたX100 Freezerのガバナンス乗っ取りと、BNB Chain上のNEMトークンの流動性プールに影響を及ぼした税の精算処理の欠陥を検証します。本レポートの対象範囲における推定損失額は合計で約557万 USDです。内訳は、代表例として取り上げるX100のトランザクションによる損失が約475万 USD、NEMプールのインシデントによる損失が約82.0万 USDです。この合計には、別途報告された、その後のX100からの資金奪取は含まれません。

Best Security Auditor for Web3

Validate design, code, and business logic before launch. Aligned with the highest industry security standards.

BlockSec Audit