Chapter 09
サイドチャネル攻撃 — 消費電力から鍵が出てくる
この章がなぜ必要なのか——「暗号が数学的に安全」でも、実装から漏れるから.
AES-256 の鍵空間は \(2^{256}\) で、総当たりは不可能である。 だが実装が動いている物理的な装置は、 演算内容に応じて消費電力・処理時間・電磁波を変化させる。
その変化を測ると、鍵が出てくる。 しかも、条件が整えば数分から数時間で。
この章で使う既出の用語(定義は各リンク先). デフォルトパスワード(01 章 5 節)、数万円(01 章 2 節)、不可能(04 章 3 節)、物理攻撃(04 章 6 節)、定時間比較(05 章 7 節)、サイドチャネル(07 章 8 節)、フォールト(07 章 8 節)、AES(08 章 8 節)、libsodium(08 章 7 節)、マスキング(08 章 6 節)
1. サイドチャネルとは何か
| サイドチャネル | 観測方法 | 必要な機材 |
|---|---|---|
| 処理時間 | 応答時間を測る | PC だけ(リモートでも可能な場合がある) |
| 消費電力 | 電源ラインに抵抗を入れて電圧を測る | オシロスコープ(数万円〜) |
| 電磁放射 | 磁界プローブを近づける | プローブ + オシロ(非接触) |
| キャッシュ | 自分のアクセス時間から他プロセスの動作を推定 | ソフトウェアのみ(主に Cortex-A / PC) |
| フォールト応答 | 誤り時の挙動の違い | 10 章 |
電磁放射による攻撃が実務的には厄介である.
チップに触れる必要がない。 パッケージの上にプローブを置くだけでよい。 基板を改造する必要も、電源ラインに介入する必要もない。
しかも空間分解能があるので、 「チップのこの部分だけ」を狙って観測できる。 AES エンジンの真上にプローブを置けば、ノイズの少ない波形が取れる。
2. タイミング攻撃 — 最も基本的で、最も見落とされる
典型的な脆弱コード
/* ★ 危険: 早期リターンする比較 */
int compare_mac(const uint8_t *a, const uint8_t *b, size_t len)
{
for (size_t i = 0; i < len; i++) {
if (a[i] != b[i]) return 0; /* ← 一致しなくなった位置で抜ける */
}
return 1;
}攻撃者は 1 バイトずつ MAC を復元できる。
定時間実装
/* ★ 正しい: 常に全バイトを比較し、実行時間が入力に依存しない */
int compare_mac_ct(const uint8_t *a, const uint8_t *b, size_t len)
{
uint8_t diff = 0;
for (size_t i = 0; i < len; i++) {
diff |= (uint8_t)(a[i] ^ b[i]); /* 差分を溜める */
}
return (diff == 0); /* 最後に 1 回だけ判定 */
}定時間実装の原則:
| 原則 | 内容 |
|---|---|
| 秘密値で分岐しない | if (secret) { ... } を書かない |
| 秘密値でメモリアドレスを決めない | table[secret] はキャッシュ攻撃の的になる |
| 早期リターンしない | 常に同じ処理量を実行する |
| 秘密値で除算しない | 除算命令は値によって時間が変わる CPU がある |
既存ライブラリの定時間実装を使うこと.
- Mbed TLS:
mbedtls_ct_memcmp()- libsodium:
sodium_memcmp()- OpenSSL:
CRYPTO_memcmp()自分で書かない。 特に「コンパイラが最適化で分岐を復活させる」ことがあり、 ソースが定時間でもバイナリが定時間とは限らない。
RSA と ECC のタイミング攻撃
素朴な冪乗計算(square-and-multiply)は、指数のビットが 1 か 0 かで処理が変わる。
for each bit of exponent:
square(); /* 常に実行する */
if (bit == 1) multiply(); /* ★ ビットが 1 のときだけ実行する */処理時間を測れば、指数(= 秘密鍵)のビット列が分かる。
対策:
| 対策 | 内容 |
|---|---|
| Montgomery ladder | ビットの値によらず常に同じ演算列を実行する |
| 常時実行 (always-multiply) | ビットが 0 でも掛け算し、結果を捨てる |
| ブラインディング | 秘密値をランダム値で撹乱してから演算する |
3. 電力解析 — SPA と DPA
SPA(単純電力解析)
1 本の波形を見るだけで秘密が分かる場合がある。
波形を目で見るだけで鍵のビット列が読める。 これは対策なしの素朴な実装で実際に起きる。
DPA(差分電力解析)— 本命
SPA が効かない場合でも、統計的手法で鍵が取れる。
電力解析の原理を見る
漏洩モデルとノイズ、波形数を変えて、相関がどう立ち上がるかを確かめられる。
原理:
CMOS 回路の消費電力は、ビットが変化した数(ハミング距離)や 1 のビット数(ハミング重み)に比例する成分を持つ。
AES の場合、最初のラウンドの S-Box 出力が狙われる。
ここで \(p\) は平文の 1 バイト(既知)、\(k\) は鍵の 1 バイト(未知、256 通り)。
攻撃の手順:
| 順 | やること |
|---|---|
| 1 | ランダムな平文で暗号化させ、数百〜数万本の電力波形を記録する |
| 2 | 鍵バイトの候補 \(k'\) を 0〜255 のそれぞれについて、各波形の中間値 \(v = \text{SBox}(p \oplus k')\) を計算する |
| 3 | その予測消費電力 \(\text{HW}(v)\) と、実測波形の各時点の値との相関係数を計算する |
| 4 | 正しい鍵バイトのときだけ、ある時点で相関が跳ね上がる |
| 5 | 16 バイト分を独立に繰り返す |
ここが決定的に重要である: 探索空間が掛け算にならない.
AES-128 の鍵は 16 バイト。総当たりなら \(256^{16} = 2^{128}\) 通り。
だが DPA では、16 バイトを 1 バイトずつ独立に求められる。 必要な試行は \(256 \times 16 = 4096\) 通りの計算だけである。
\[ 2^{128} \quad \longrightarrow \quad 4096 \]これが「暗号が数学的に強くても実装で破れる」の意味である。
必要な波形数の目安
| 実装 | 波形数の目安 |
|---|---|
| 対策なしのソフトウェア AES | 数百〜数千本 |
| 対策なしのハードウェア AES | 数千〜数万本 |
| 1 次マスキング実装 | 数十万〜数百万本(高次 DPA が必要) |
| 高次マスキング + シャッフリング | 実用上困難な本数 |
波形の取得は自動化できる。 1 秒に数百〜数千波形を取れるので、 数千本なら数分、数十万本でも数時間で集まる。
4. 電磁解析(EMA)
原理は電力解析と同じだが、取得方法が違う。
| 特徴 | 内容 |
|---|---|
| 非接触 | パッケージの上にプローブを置くだけ |
| 空間分解能 | チップ上の特定の回路だけを狙える |
| ノイズが少ない場合がある | 電源ラインの平滑化コンデンサの影響を受けない |
| 基板改造が不要 | 電源ラインに抵抗を入れる必要がない |
BGA パッケージや、電源が厳重にフィルタされた基板でも、EMA なら通る.
「電源ラインにアクセスできないから安全」という想定は成り立たない。 物理攻撃を想定するなら、EMA を前提にする必要がある。
5. 対策
対策 1: マスキング(最も重要)
中間値をランダム値で撹乱し、消費電力と秘密の相関を断つ。
| 次数 | 内容 | 破るには |
|---|---|---|
| 1 次マスキング | ランダム値 1 個で撹乱 | 2 次 DPA(2 点の積を取る)が必要 |
| d 次マスキング | ランダム値 d 個で撹乱 | (d+1) 次 DPA が必要。必要な波形数が指数的に増える |
マスキングは「正しく実装するのが極めて難しい」.
- コンパイラの最適化でマスクが外れる
- CPU の内部でマスクされた値とマスクなしの値が同じレジスタを通る(トランジション漏洩)
- S-Box をマスクしたまま計算するのが難しい(テーブル再計算が必要)
自作しないこと。 DPA 対策済みのハードウェアエンジンを使うのが正解である。
対策 2: 隠蔽(Hiding)
信号対雑音比を下げる。
| 手法 | 内容 |
|---|---|
| シャッフリング | S-Box 16 個の処理順序を毎回ランダムに入れ替える |
| ダミー演算 | 無関係な演算をランダムに挿入する |
| ランダム遅延 | 処理の間にランダムな待ちを入れる |
| クロックジッタ | クロック周波数を微妙に揺らす |
| 電力平坦化回路 | ハードウェアで消費電流を一定に保つ |
隠蔽だけでは不十分である.
シャッフリングやランダム遅延は、波形を位置合わせ(アライメント)すれば無効化される。 攻撃者は相関ベースのアライメント手法を使って、揺らぎを除去できる。
隠蔽は「波形数を増やさせる」効果しかない。 \(n\) 通りのシャッフルなら、必要な波形数が約 \(n^2\) 倍になる程度である。
マスキング(撹乱)と隠蔽(雑音)を組み合わせるのが実際の設計である。
対策 3: プロトコル・システムレベル
そもそも同じ鍵で大量の暗号化をさせない。
| 手法 | 内容 |
|---|---|
| 鍵の使用回数制限 | 同じ鍵での暗号化回数に上限を設ける |
| フレッシュな鍵の導出 | セッションごとに鍵を派生させる |
| リーク耐性のあるプロトコル | 鍵を都度更新する構成にする |
| レート制限 | 短時間に大量の要求を受け付けない |
これが実は最も費用対効果が高い場合がある.
DPA には数千本以上の波形が要る。 「同じ鍵での暗号化は 100 回まで」という制約をプロトコルで課せば、 必要な波形が集まらない。
ハードウェアを変えずに、プロトコル設計だけで防げる場合がある。
対策 4: 認証済みハードウェアを使う
| 認証 | 物理攻撃耐性の評価 |
|---|---|
| PSA Certified Level 3 | サイドチャネル・フォールトへの耐性を含む |
| SESIP 4 以上 | 同上 |
| CC AVA_VAN.4 以上 | 同上 |
| CC AVA_VAN.5(EAL6+ など) | 最も高い。セキュアエレメントが取得(22 章) |
最も確実な対策は「その用途にセキュアエレメントを使う」ことである.
ATECC608、SE050、OPTIGA Trust M などは、 サイドチャネル対策を前提に設計され、第三者評価を受けている(22 章)。
MCU 内蔵の暗号エンジンで DPA 耐性まで持つものは限られる。 「機器の長期秘密鍵はセキュアエレメントに、 セッション鍵は MCU の暗号エンジンで」という役割分担が現実的である。
6. どこまでやるべきか
02 章の攻撃者クラスに戻る。
| 攻撃者クラス | サイドチャネル対策の必要性 |
|---|---|
| クラス 1〜2(好奇心・愛好家) | 不要。もっと安い攻撃手段がある |
| クラス 3(犯罪者) | 場合による。「1 台破ると全台破れる」構造があるなら必要 |
| クラス 4(競合他社・専門ラボ) | 必要 |
| クラス 5(国家) | 必要。かつ、それでも十分とは限らない |
優先順位を間違えないこと.
DPA 対策に投資する前に、確認すべきことがある。
これらが空いているなら、そちらから取られる。 攻撃者は最も安い経路を選ぶ(02 章の攻撃ツリー)。
DPA 対策は「他が全部固まってから」検討する項目である。
7. この章のまとめ
| ポイント | 内容 |
|---|---|
| サイドチャネル | 時間・電力・電磁波・キャッシュ。設計者が想定していない経路 |
| EMA の脅威 | 非接触で、空間分解能がある。基板改造が不要 |
| タイミング攻撃 | 最も基本的。秘密値で分岐しない・早期リターンしない |
| 定時間比較 | ライブラリの ct_memcmp を使う。自作しない |
| DPA の核心 | 16 バイトを 1 バイトずつ独立に求められる。\(2^{128} \to 4096\) |
| 必要な波形数 | 対策なしで数百〜数千本。数分で集まる |
| マスキング | 最も重要な対策。だが正しい実装が極めて難しい |
| 隠蔽 | 波形数を増やさせるだけ。マスキングと併用する |
| システムレベル | 同じ鍵の使用回数を制限する。費用対効果が高い |
| 確実な対策 | セキュアエレメント(AVA_VAN.5 相当)に長期鍵を置く |
| 優先順位 | 基本の穴を全部塞いでから。DPA 対策は最後 |
次章では、もう 1 つの物理攻撃—— 「電圧をひと突きすると if 文が飛ぶ」フォールトインジェクションを扱う。