サイドチャネル攻撃の原理:タイミング・電力・キャッシュ
アルゴリズムが理論上安全でも実装は秘密を漏らす。処理時間・消費電力・キャッシュの観測から鍵を盗む手口の原理と、定数時間実装による防ぎ方が分かる。
- 1.サイドチャネル攻撃は暗号アルゴリズムの数学ではなく、実装の物理的・計測可能な副産物(時間・電力・キャッシュ状態)を観測して秘密を復元する。
- 2.秘密データに依存して処理時間・分岐・メモリアクセス先が変わると漏れる。タイミング攻撃、電力解析(SPA/DPA)、Flush+Reload などキャッシュ攻撃が代表。
- 3.対策の核は定数時間実装。秘密に依存した分岐・テーブル参照・早期 return を排し、計測値を秘密と無相関にする。標準ライブラリの実装に任せるのが原則。
攻撃の前提:正しいアルゴリズムが「漏らす」
サイドチャネル攻撃は、暗号アルゴリズムそのものを数学的に破るのではなく、**そのアルゴリズムを実行する実装が外部に漏らす副次的な情報(サイドチャネル)**を観測して秘密を復元します。AES や RSA の理論的強度がいくら高くても、実装が秘密の値に応じて観測可能な振る舞いを変えるなら、攻撃者はそこから鍵を盗めます。
漏れる情報源は物理量や計測量です。代表的なものを押さえます。
- 時間:処理にかかる時間が秘密に依存して変わる(タイミング攻撃)。
- 電力:CPU やスマートカードの消費電力が処理内容に依存する(電力解析 SPA/DPA)。
- キャッシュ:どのメモリ位置にアクセスしたかがキャッシュ状態として観測できる(Flush+Reload など)。
- その他、電磁波、音、温度、エラーメッセージの差なども channel になり得ます。
通常の暗号解読は「暗号文だけを見て鍵を当てる」モデルですが、サイドチャネルでは攻撃者が実行環境を計測できる前提に立ちます。スマートカードを手元で動かせる、同じ物理マシン上に自分のプロセスを置ける、ネットワーク越しに応答時間を測れる――こうした観測能力こそが武器です。だから暗号の基礎で言うアルゴリズム強度とは別軸の問題になります。
タイミング攻撃:処理時間が秘密を映す
最も基本的なのがタイミング攻撃です。秘密の値によって実行時間が変わると、攻撃者は時間を測るだけで秘密を推定できます。古典的な例が、文字列やトークンの比較を1バイトずつ照合し、不一致を見つけた瞬間に return する実装です。
# 危険:先頭から一致した分だけ比較が進む → 早く返るほど一致が少ない
def insecure_equal(a, b):
if len(a) != len(b):
return False
for x, y in zip(a, b):
if x != y: # 不一致を見つけた瞬間に抜ける
return False # → 一致したバイト数が処理時間に漏れる
return True
攻撃者は先頭バイトを総当たりし、**わずかに処理時間が伸びた候補が「正解の1バイト」**だと分かります。これを繰り返せば、256^n の総当たりを 256×n 回程度に落とせます。RSA の復号でも、剰余べき乗(modular exponentiation)の各ビットで秘密指数に応じた処理が走るため、応答時間の統計から指数ビットを当てる攻撃が成立します(Kocher 1996)。
対策は比較を定数時間にすることです。全バイトを最後まで走査し、差分を XOR で累積して最後にまとめて判定します。
# 安全:常に全バイトを走査し、途中で抜けない(定数時間)
def constant_time_equal(a, b):
if len(a) != len(b):
return False
diff = 0
for x, y in zip(a, b):
diff |= x ^ y # 1ビットでも違えば diff に痕跡が残る
return diff == 0 # 比較回数・経路は中身に依存しない
実務では自作せず、Python の hmac.compare_digest や各言語の constant_time_compare を使います。
電力解析:SPA と DPA
スマートカードや IoT デバイスのように攻撃者が物理的に触れる対象では、消費電力が強力なチャネルになります。CMOS 回路はビットを 0→1 に切り替える瞬間に電流を多く消費するため、処理中のデータや命令と電力波形が相関します。
- SPA(Simple Power Analysis):電力波形を1回ないし数回観測し、波形の形を直接読む。たとえば RSA の二乗・乗算アルゴリズムで、秘密指数のビットが 1 のときだけ余分な乗算が走ると、波形にその凹凸が現れ、ビット列を直読できる。
- DPA(Differential Power Analysis):多数回の電力波形を集め、鍵の候補ごとに「この中間値ならこの時点の消費電力が高いはず」という仮説を立て、統計的相関で正しい候補を絞り込む。1波形では雑音に埋もれる微小な差を、平均化と差分で浮かび上がらせる。
SPA は波形が読めるほど特徴的でないと使えませんが、DPA は統計なので、1波形では見えない数ミリボルト級の差でも、数千〜数万波形を集めれば抽出できます。「波形を見ても何も分からない」ことは安全の証明になりません。対策にはマスキング(中間値を乱数で攪乱し相関を切る)やハイディング(消費電力を平準化・ランダム化する)といった、ハードウェア/実装レベルの専用手法が要ります。
キャッシュ攻撃:Flush+Reload
現代のサーバーで現実的脅威なのがキャッシュタイミング攻撃です。CPU キャッシュにあるデータへのアクセスは数サイクル、メインメモリからだと数百サイクルかかります。この速度差を使って「相手がどこにアクセスしたか」を観測します。秘密に依存してアクセスするテーブルの位置(たとえば AES の S-box 参照や、鍵ビットで分岐する処理)が変われば、それがアクセスパターンとして漏れます。
代表的手法 Flush+Reload は、攻撃者と被害者が同じ物理メモリ(共有ライブラリのページなど)を共有している状況で成立します。
1. Flush : 攻撃者が対象アドレスをキャッシュから追い出す(clflush 命令)
2. Wait : 被害者プロセスに暗号処理を実行させる
3. Reload : 攻撃者が同じアドレスを読み、アクセス時間を測る
→ 速ければ「被害者がそこを触った」(キャッシュに載った)
→ 遅ければ「触っていない」(メモリから読み直し)
これを秘密依存のアクセス箇所に対して繰り返すと、被害者が参照した位置=秘密の値が漏れます。クラウドのマルチテナント環境(同一物理ホスト上の別 VM やコンテナ)で、隣の利用者の鍵を盗む攻撃が実証されています。Spectre / Meltdown も、投機実行で読んだ秘密をキャッシュ状態に変換し、このキャッシュ計測で読み出す点で同系統です。
キャッシュ攻撃が怖いのは、攻撃者が被害者のメモリを直接読めなくても、共有キャッシュという間接経路だけで秘密を抜ける点です。「メモリ分離されているから安全」は通りません。対策は、秘密に依存したメモリアクセス(鍵で引くテーブル参照、鍵ビットによる分岐)をそもそも作らないこと。AES では S-box をルックアップせずビット演算で実装する(bitsliced AES)か、ハードウェア命令 AES-NI を使い、テーブル参照自体を消します。
対策の原則:定数時間実装
個別手法は違っても、防御の核心は一つです。観測可能な量(時間・電力・アクセス先)を、秘密データと無相関にすること。これを実装レベルで満たすのが定数時間(constant-time)実装です。具体的には、秘密の値に対して次を禁じます。
- 秘密に依存した分岐(
if (secret_bit) { ... }):実行経路・時間・電力が変わる。 - 秘密に依存した早期 return / ループ回数:処理量が漏れる。
- 秘密をインデックスにしたメモリアクセス(
table[secret]):キャッシュに位置が漏れる。 - 秘密に依存した可変長処理(除算の桁数など命令ごとに時間が違うもの)。
代わりに、常に同じ命令列・同じ回数・同じアクセスパターンで計算し、結果の選択は分岐ではなく**ビットマスクや条件付き move(cmov)**で行います。下は「条件で値を選ぶ」を分岐なしで書く典型です。
/* 危険:cond が秘密に依存すると分岐で経路が変わり漏れる */
/* if (cond) r = a; else r = b; */
/* 安全:分岐せずビット演算で選択(経路は一定)*/
uint32_t select_ct(uint32_t cond, uint32_t a, uint32_t b) {
uint32_t mask = (uint32_t)(-(int32_t)(cond & 1)); /* cond=1→全ビット1, 0→全ビット0 */
return (a & mask) | (b & ~mask); /* 常に両方を評価して選ぶ */
}
| チャネル | 漏れの原因 | 代表的な攻撃 | 主な対策 |
|---|---|---|---|
| タイミング | 秘密に依存した分岐・早期return・可変時間命令 | トークン比較、RSA タイミング | 定数時間比較・定数時間べき乗 |
| 電力 | データ・命令と消費電力の相関 | SPA / DPA | マスキング・ハイディング |
| キャッシュ | 秘密に依存したメモリアクセス位置 | Flush+Reload, Spectre | テーブル参照排除・bitslice・AES-NI |
「アルゴリズムが安全=実装も安全」ではない、が核心です。(1) サイドチャネルは数学ではなく実装の副産物を突く。(2) タイミング攻撃の典型は早期 return する比較で、対策は定数時間比較。(3) DPA は統計なので 1 波形で見えなくても破れる。(4) キャッシュ攻撃は共有キャッシュ経由でメモリ分離を回避する。(5) 防御の原則は秘密に依存した分岐・テーブル参照・処理時間を作らないこと。
実務での向き合い方
最大の教訓は、暗号の基礎と同じく「暗号は自作しない」に尽きます。定数時間性は、ソースを見ても保証しにくく、コンパイラの最適化が分岐を勝手に生んだり、CPU の投機実行が経路を変えたりと、言語より下の層で崩れます。だからこそ、libsodium や各言語標準の監査済み実装を使うのが第一原則です。
自前で機微な比較を書くなら定数時間関数を、パスワード照合ならパスワードの安全な保存で扱う専用関数を使います。クラウドでは、鍵を扱う処理を専用ハードウェア(HSM / 鍵管理サービス)に逃がし、共有環境からアクセスパターンを観測されにくくするのも有効です。そして、こうした実装上の漏れは設計レビューだけでは見落とすため、ペネトレーションテストや専用ツール(dudect など、入力に対する実行時間の分布差を統計検定する)による実測での検証が欠かせません。「理論上安全」と「計測しても漏れない」は別物だと押さえてください。
セキュリティ Article
サイドチャネル攻撃の原理:タイミング・電力・キャッシュを実務で読む
TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。
解決すること
サイドチャネル
比較で見る軸
難易度: advanced / カテゴリ: セキュリティ / タグ数: 5
導入後に効く点
秘密データに依存して処理時間・分岐・メモリアクセス先が変わると漏れる。タイミング攻撃、電力解析(SPA/DPA)、Flush+Reload などキャッシュ攻撃が代表。
先に潰すリスク
用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。
- 難易度
- advanced
- カテゴリ
- セキュリティ
- タグ数
- 5
判断チェックリスト
- 自社の用途が「サイドチャネル / 暗号」に近いか確認する。
- 強みである「サイドチャネル攻撃は暗号アルゴリズムの数学ではなく、実装の物理的・計測可能な副産物(時間・電力・キャッシュ状態)を観測して秘密を復元する。」が本当に評価軸になるか確認する。
- 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
- 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
- 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
- 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。