レインボーテーブルとハッシュ関数の関係は?作成方法も解説!(時間とメモリのトレードオフ:チェーン:計算コストなど)
パスワードを安全に扱う仕組みを理解するうえで、ハッシュ関数とレインボーテーブルの関係は重要なテーマです。
レインボーテーブルは、ハッシュ値から元の候補文字列を効率よく探すために作られる事前計算済みのデータ構造を指します。
一方で、適切なソルトや遅いパスワードハッシュ関数を用いれば、レインボーテーブルによる攻撃の効果は大きく下げられます。
この記事では、ハッシュ関数の基本、レインボーテーブルのチェーン構造、作成時の考え方、時間とメモリのトレードオフ、対策までを順に整理します。
レインボーテーブルとハッシュ関数の関係

それではまず、レインボーテーブルとハッシュ関数の関係について解説していきます。
ハッシュ関数による一方向変換
ハッシュ関数は、入力したデータから一定の規則で固定長に近いハッシュ値を生成する関数です。
パスワードが入力値であれば、その結果として英数字の並びであるハッシュ値が得られます。
代表例にはSHA-256やSHA-512がありますが、パスワード保存では単純な高速ハッシュ関数をそのまま使うことは推奨されません。
ハッシュ関数には、入力から出力を計算しやすい一方、出力だけから元の入力を直接復元しにくいという性質があります。
この性質は一方向性と呼ばれ、認証システムでパスワードそのものを保存しないための土台になります。
ただし、元の文字列を数学的に逆算できないことと、候補を大量に試して一致するものを見つけられないことは別の話です。
短いパスワードや辞書に載る単語であれば、候補を入力してハッシュ化し、保存済みの値と比較する方法で見つかる可能性があります。
入力値が password の場合を考えます。
ハッシュ関数に入力すると、password 自体ではなく、一定の計算結果であるハッシュ値が出力されます。
攻撃者は候補文字列を次々にハッシュ化し、対象のハッシュ値と一致する候補を探します。
レインボーテーブルが担う事前計算
レインボーテーブルは、候補となる平文とハッシュ値の対応を、あらかじめ計算しておく考え方から生まれました。
対象のハッシュ値を入手してから毎回すべての候補を計算するより、前もって計算結果を保存しておけば、照合に必要な時間を短縮できます。
ここで重要になるのが、単純な対応表をそのまま巨大化させず、チェーンという形に圧縮する発想です。
レインボーテーブルは検索時間を短縮する代わりに保存領域を使う手法であり、計算資源とストレージ資源の交換関係を利用しています。
攻撃者にとっては、同じハッシュ方式で多数のパスワードが保存されている環境ほど、作成済みテーブルを使い回しやすくなります。
管理者側から見れば、同一のパスワードでもユーザーごとに異なる値になる仕組みを設けることが防御の要点です。
逆変換ではなく候補探索
レインボーテーブルを説明する際、ハッシュを復号する表現が使われることがあります。
しかし、厳密にはハッシュ関数を暗号のように逆変換しているわけではありません。
実際に行われるのは、対象のハッシュ値に対応し得る候補文字列を、事前計算した連鎖の中から探索する処理です。
そのため、テーブルの対象外となる長さのパスワード、文字種、辞書にないランダムな文字列は、表が存在しても見つからない場合があります。
また、同じハッシュ値になる入力が理論上あり得る衝突と、特定の入力候補を探す問題も区別して理解する必要があります。
レインボーテーブルは万能な復元手段ではなく、探索範囲を限定したうえで高速な照合を可能にする仕組みです。
レインボーテーブルはハッシュ値を元に戻す魔法の一覧ではありません。
定義済みの候補空間から、一致する可能性が高い入力を効率よく探すための事前計算データです。
ハッシュ値探索におけるチェーン構造
続いては、レインボーテーブルの中心となるチェーン構造を確認していきます。
削減関数による連鎖
チェーンでは、平文をハッシュ化した後、そのハッシュ値を再び平文候補の形式へ変換します。
この変換に使うものが削減関数です。
削減関数はハッシュ関数の逆関数ではなく、ハッシュ値をパスワード候補のような形式に機械的に対応付けるための関数です。
平文候補をハッシュ化し、削減関数で次の平文候補を作る処理を繰り返すことで、長いチェーンが形成されます。
保存時にはチェーン内の全要素ではなく、開始点と終了点を中心に保持するため、必要な容量を抑えられます。
この仕組みが、時間とメモリのトレードオフを成立させる基盤です。
チェーンの概念例です。
開始平文からハッシュ値を作り、削減関数で次の候補文字列へ変換します。
この処理を複数回続け、最初の候補と最後の候補を記録します。
| 処理段階 | 扱う値 | 目的 |
|---|---|---|
| 開始点 | 候補文字列 | チェーンを生成する起点 |
| ハッシュ化 | ハッシュ値 | 対象システムと同じ計算結果を得る工程 |
| 削減 | 次の候補文字列 | チェーンを継続する工程 |
| 終了点 | 候補文字列 | テーブルに保存し検索に使う値 |
複数の削減関数を使う理由
初期のチェーン方式では、同じ削減関数を繰り返して使うため、異なるチェーンが途中で合流しやすい問題がありました。
複数のチェーンが合流すると、同じ計算を重複して行ったことになり、候補空間のカバー率が下がります。
レインボーテーブルでは、チェーン内の位置ごとに異なる削減関数を使うことで、この合流の影響を抑えます。
色の異なる削減処理を順に通すイメージから、レインボーという名称が使われています。
位置ごとに変換方法が異なれば、ある段階で一致した値が別の段階では一致しにくくなり、探索範囲をより有効に使えます。
ただし、設計を複雑にしても候補空間が小さすぎる場合やチェーン数が多すぎる場合には、重複を完全になくすことはできません。
チェーン衝突と探索漏れ
チェーン構造には、異なる開始点から始めても途中で同じ候補へ到達するチェーン衝突が起こり得ます。
衝突後は同じ経路をたどるため、保存したチェーン数に対して実際に探索できる候補数が少なくなります。
また、対象のハッシュ値がチェーンの途中に存在していても、終了点の照合だけでは候補をすぐに断定できません。
終了点らしい値を見つけた後、対応する開始点から改めてチェーンを再生成し、途中に対象ハッシュ値が現れるかを検証します。
この再計算があるため、レインボーテーブルは容量を節約できる一方、照合処理が完全に一回で終わるわけではありません。
保存量の削減と再計算の増加は、チェーン方式を理解するうえで欠かせない関係です。
時間とメモリのトレードオフ
続いては、レインボーテーブルで重視される時間とメモリのトレードオフを確認していきます。
総当たり攻撃との違い
総当たり攻撃では、対象ハッシュ値を得た後に、考えられる候補を一つずつハッシュ化して一致を調べます。
保存領域はほとんど不要ですが、候補数が増えるほど実行時間も増加します。
単純な対応表では、平文とハッシュ値をすべて保存するため、検索時間を短縮しやすい反面、莫大な保存容量が必要になります。
レインボーテーブルは両者の中間に位置し、チェーンの開始点と終了点を保存することで、保存容量を抑えつつ検索時間の短縮を狙います。
このため、攻撃対象の文字種や最大文字数が限定されているほど、事前計算の効果を出しやすくなります。
| 手法 | 事前計算 | 保存容量 | 対象取得後の時間 | 特徴 |
|---|---|---|---|---|
| 総当たり攻撃 | 少ない | 少ない | 長くなりやすい | 条件変更に対応しやすい |
| 単純な対応表 | 多い | 非常に多い | 短い | 照合は速いが容量負担が大きい |
| レインボーテーブル | 多い | 中程度 | 中程度 | チェーンで容量を圧縮する |
| 辞書攻撃 | 少ない | 少ない | 候補次第 | よく使われる語に強い |
候補空間と計算コスト
レインボーテーブルの規模は、対象にするパスワードの文字種、最小文字数、最大文字数、ハッシュ方式によって大きく変わります。
たとえば英小文字だけを対象にする場合と、英大文字、数字、記号まで含める場合では、候補数に大きな差が出ます。
1文字増えるだけでも組み合わせ数は急増するため、十分に長くランダムなパスワードは事前計算の対象にしにくくなります。
さらに、ハッシュ計算が高速であるほど大量の候補を処理しやすく、攻撃側にとって有利になります。
反対に、意図的に計算コストを高くするパスワードハッシュ関数は、テーブル作成の負担も照合時の負担も増やします。
候補空間の広さと一回のハッシュ計算にかかる負荷の両方が、安全性を左右します。
文字種が26種類で長さが8文字までの場合、候補数は短い文字列から8文字列までの組み合わせを合計して考えます。
文字種を増やしたり最大文字数を伸ばしたりすると、必要な事前計算量と保存容量は急激に大きくなります。
そのため、長く無作為性の高いパスフレーズは、単純な短いパスワードより有利です。
実務における資源配分
レインボーテーブルの話題は攻撃技術として語られがちですが、防御側が必要なコストを考える材料にもなります。
認証基盤を設計する際は、利用者のログイン待ち時間と、攻撃者に強いる計算負荷のバランスを取る必要があります。
高速なSHA-256を大量に繰り返す方式は、一般的なデータ整合性確認には便利でも、パスワード保存には不十分になりやすい点に注意が必要です。
パスワードにはbcrypt、scrypt、Argon2のように、意図的に計算負荷やメモリ使用量を増やせる専用方式が使われます。
これらの方式では、攻撃者が大量の候補を試すコストも高くなるため、事前計算の経済性を下げる効果が期待できます。
パスワード保存で重要なのは、ハッシュ値を作ることだけではありません。
ユーザーごとのソルトと、十分な計算負荷を持つ専用ハッシュ方式を組み合わせることが実務上の基本です。
レインボーテーブルの作成手順
続いては、レインボーテーブルの作成方法を概念的に確認していきます。
対象条件の設計
テーブルを作成する前には、どのような候補文字列を対象にするかを定義します。
対象となる文字種、文字列の長さ、使用するハッシュ関数、削減関数の設計、チェーンの長さ、生成するチェーン数などを決めます。
この条件設定はテーブルの性能を左右します。
対象を広く取りすぎると計算量と保存量が膨らみ、狭くしすぎると照合したい値をカバーできません。
教育目的で構造を理解する場合には、短い英小文字だけのような小さな候補空間を設定すると、チェーンの動きを追いやすくなります。
実在サービスの認証情報を対象にした無断利用は不正行為につながるため、検証は自分で用意した安全なデータだけで行う必要があります。
開始点と終了点の記録
条件を定めたら、ランダムまたは規則的に選んだ開始平文からチェーンを生成します。
各段階でハッシュ関数を適用し、段階ごとに設定された削減関数を通して次の候補文字列を作ります。
あらかじめ決めた長さまで進めたら、そのチェーンの開始点と終了点を一組として保存します。
この組を多数作成し、終了点で並べ替えや検索ができるようにしておくと、照合時の処理を効率化できます。
保存する情報を絞ることがレインボーテーブルの利点ですが、チェーン再生成のために開始点を失わないようにする必要があります。
終了点だけでは途中経路を確認できないため、開始点との対応関係が重要になります。
照合時の検証処理
対象ハッシュ値を照合する際は、それを各段階に置いた場合の終了候補を順に計算します。
計算した終了候補がテーブル内の終了点と一致すれば、該当チェーンが見つかった可能性があります。
次に、その終了点と対応する開始点からチェーンを再生成します。
再生成の途中で対象ハッシュ値が現れれば、その直前の候補文字列が求める平文候補になります。
一致した終了点があっても、再生成の途中に対象値がない場合は誤検出です。
この検証工程があるため、レインボーテーブルの検索は単純な辞書参照より複雑ですが、事前計算済みの連鎖を活用できます。
作成時に省略したチェーン内部の情報は、照合時に再計算して確認します。
容量を抑える代わりに検証計算が必要になる点が、レインボーテーブルの特徴です。
ソルトとパスワードハッシュの防御設計
続いては、レインボーテーブルへの対策として重要なソルトとパスワードハッシュの防御設計を確認していきます。
ソルトによる使い回し対策
ソルトは、パスワードをハッシュ化する前に追加する、ユーザーごとに異なるランダムな値です。
同じパスワードを使っていてもソルトが異なれば、保存されるハッシュ値は異なります。
その結果、共通のハッシュ方式だけを前提に作られたレインボーテーブルは、そのまま利用しにくくなります。
攻撃者はソルトごとに計算をやり直す必要があり、大規模な事前計算の価値が大幅に下がります。
ソルトは秘密にする値ではありません。
一般にはハッシュ値とともに保存されますが、十分な長さを持つ一意でランダムな値を各パスワードに使うことが重要です。
| 保存方式 | 同じパスワードの結果 | 事前計算への強さ | 評価 |
|---|---|---|---|
| 高速ハッシュのみ | 同じ値になりやすい | 弱い | パスワード保存には不適切 |
| 固定ソルト付き | 同じ値になりやすい | 限定的 | 全体共通では不足しやすい |
| 個別ランダムソルト付き | 異なる値になる | 強い | 基本的な防御策 |
| 個別ソルトと専用方式 | 異なる値になる | より強い | 実務で推奨される構成 |
遅いハッシュ関数の選択
パスワードは、一般的なファイル検証とは異なり、攻撃者が候補を何度も試せる前提で守る必要があります。
そこで、パスワード保存には計算回数、メモリ使用量、並列処理への耐性を調整できるアルゴリズムが選ばれます。
Argon2、bcrypt、scrypt、PBKDF2などは、単純な高速ハッシュよりも候補試行のコストを高めるために利用されます。
特にArgon2やscryptはメモリ使用量を重視した設計が可能であり、GPUなどを使った大量並列処理に対する負担を増やす狙いがあります。
設定値は一度決めて終わりではありません。
サーバー性能、ログイン頻度、脅威の変化を踏まえ、運用中にも調整を検討する姿勢が求められます。
利用者と運用者の実践事項
利用者は、短い単語だけのパスワードや、複数サービスでの使い回しを避けることが大切です。
長く覚えやすいパスフレーズを使い、必要に応じてパスワードマネージャーで高いランダム性を確保するとよいでしょう。
多要素認証を有効にすれば、仮にパスワード候補が推測されても、追加の認証要素が防御層になります。
運用者は、平文パスワードを保存しないこと、個別ソルトを使うこと、専用ハッシュ方式を採用することを徹底します。
また、流出時の影響を減らすため、ログ監視、認証試行の制限、通知手順、パスワード変更の導線まで含めた対策が必要です。
レインボーテーブル対策は単独の設定ではなく、認証設計全体の一部として考えることが重要です。
レインボーテーブルとハッシュ関数の関係のまとめ
ここまでの内容をまとめます。
レインボーテーブルは、ハッシュ関数で得られる値と候補文字列の関係を、チェーンとして事前計算しておく仕組みです。
開始点と終了点を保存し、必要に応じてチェーンを再計算するため、単純な対応表より保存容量を抑えられます。
その代わり、作成に必要な計算コスト、チェーン衝突、照合時の検証処理といった課題もあります。
時間とメモリのトレードオフを理解すると、なぜ短く単純なパスワードが危険になりやすいのかも見えやすくなるでしょう。
防御の中心は、ユーザーごとにランダムなソルトを付け、Argon2やbcryptなどのパスワード専用ハッシュ方式を適切な設定で用いることです。
さらに、長く固有のパスワード、多要素認証、認証試行の監視を組み合わせれば、レインボーテーブルを含むパスワード攻撃への耐性を高められます。