
2FA開発で知ったArgon2:パスワードハッシュ化の新時代
「パスワードのハッシュ化?MD5でいいでしょ」
2FA(二要素認証)の開発を始めたとき、最初はそう思ってました。
MD5、SHA-1、SHA-256...どれも「ハッシュ関数」でしょ?違いなんてあるの?
でも、調べていくうちに、とんでもない勘違いをしていたことに気づきました。
パスワードのハッシュ化には、専用のアルゴリズムが必要なんです。
そして、その最適解がArgon2でした。
従来のハッシュ関数の問題点
MD5やSHA-1は「速すぎる」
MD5やSHA-1は、設計上、高速に動作するように作られています。
これは、データの整合性チェックやデジタル署名には最適です。でも、パスワードのハッシュ化には致命的な欠陥があります。
MD5: 1秒間に数億回のハッシュ計算が可能
SHA-1: 1秒間に数千万回のハッシュ計算が可能
これが何を意味するか?
ブルートフォース攻撃が簡単にできてしまうんです。
レインボーテーブル攻撃
レインボーテーブルとは、よく使われるパスワードとそのハッシュ値を事前に計算して保存したテーブルです。
MD5やSHA-1のような高速なハッシュ関数だと、数秒で数億パターンのハッシュを計算できます。
攻撃者がデータベースからハッシュ値を盗み出したら、レインボーテーブルと照合するだけで、多くのパスワードが即座に解読されてしまいます。
GPU攻撃の脅威
現代のGPUは、並列処理が得意です。
MD5やSHA-1のような単純なハッシュ関数は、GPUで並列実行すると、CPUの数百倍の速度で計算できます。
CPU: 1秒間に1000万回
GPU: 1秒間に100億回(1000倍!)
これでは、どんなに複雑なパスワードでも、時間をかければ解読されてしまいます。
Argon2とは
Argon2は、2015年のPassword Hashing Competitionで優勝した、パスワードハッシュ化専用のアルゴリズムです。
なぜArgon2が優勝したのか
Argon2が選ばれた理由は、3つの攻撃に対する耐性です:
- サイドチャネル攻撃に強い
- GPU攻撃に強い
- メモリ攻撃に強い
特に、メモリハードな設計が特徴的です。
メモリハードとは
メモリハードとは、計算に大量のメモリを必要とする設計のことです。
Argon2は、ハッシュ化の過程で大量のメモリを読み書きします。これにより:
- GPU攻撃が困難: GPUはメモリ帯域幅が限られている
- 専用ハードウェア攻撃が困難: メモリが高価になる
- 並列化が困難: メモリ競合が発生する
結果として、ブルートフォース攻撃のコストが劇的に上がるんです。
Argon2の3つのバリアント
Argon2には、用途に応じて3つのバリアントがあります。
Argon2i(Independent)
サイドチャネル攻撃に最も強いバリアントです。
メモリアクセスのパターンがデータに依存しないため、タイミング攻撃やキャッシュ攻撃に耐性があります。
用途:
- パスワードのハッシュ化
- 暗号鍵の導出
- 一般的な認証システム
Argon2d(Dependent)
GPU攻撃に最も強いバリアントです。
メモリアクセスのパターンがデータに依存するため、並列化が困難です。
用途:
- 仮想通貨のマイニング
- ブロックチェーン
- GPU攻撃が懸念される環境
Argon2id(Hybrid)
Argon2iとArgon2dのハイブリッドです。
最初の部分はArgon2i、残りはArgon2dで処理します。
バランスが取れた選択肢で、多くの場合、これが推奨されます。
用途:
- 一般的なアプリケーション(推奨)
- セキュリティとパフォーマンスのバランスが重要
Argon2のパラメータ
Argon2は、3つのパラメータで調整できます。
1. 時間コスト(Time Cost)
反復回数を指定します。
timeCost = 3 → 3回反復
timeCost = 10 → 10回反復
値が大きいほど、計算時間が長くなり、セキュリティが向上します。
2. メモリコスト(Memory Cost)
使用するメモリ量を指定します(キロバイト単位)。
memoryCost = 65536 → 64MB
memoryCost = 131072 → 128MB
値が大きいほど、メモリ使用量が増え、GPU攻撃が困難になります。
3. 並列度(Parallelism)
並列スレッド数を指定します。
parallelism = 1 → シングルスレッド
parallelism = 4 → 4スレッド
一般的には、CPUのコア数に合わせます。
推奨設定
OWASP(Open Web Application Security Project)の推奨設定:
Argon2id
- timeCost: 2
- memoryCost: 65536 (64MB)
- parallelism: 1
この設定で、約0.5秒の計算時間になります。
実装例
Python(argon2-cffi)
from argon2 import PasswordHasher
# ハッシュ化
ph = PasswordHasher(
time_cost=2,
memory_cost=65536,
parallelism=1,
hash_len=32,
salt_len=16
)
password = "my_secure_password"
hash = ph.hash(password)
# 結果: $argon2id$v=19$m=65536,t=2,p=1$...
# 検証
try:
ph.verify(hash, password)
print("パスワードが一致しました")
except:
print("パスワードが一致しません")
Node.js(argon2)
const argon2 = require('argon2');
// ハッシュ化
async function hashPassword(password) {
const hash = await argon2.hash(password, {
type: argon2.argon2id,
memoryCost: 65536, // 64MB
timeCost: 2,
parallelism: 1,
});
return hash;
}
// 検証
async function verifyPassword(hash, password) {
try {
await argon2.verify(hash, password);
return true;
} catch (err) {
return false;
}
}
PHP(password_hash)
PHP 7.2以降では、標準関数でArgon2が使えます。
// ハッシュ化
$options = [
'memory_cost' => 65536, // 64MB
'time_cost' => 2,
'threads' => 1,
];
$hash = password_hash('my_secure_password', PASSWORD_ARGON2ID, $options);
// 検証
if (password_verify('my_secure_password', $hash)) {
echo "パスワードが一致しました";
}
Argon2のメリット
1. セキュリティが高い
- GPU攻撃に強い: メモリハードな設計
- レインボーテーブル攻撃に強い: ソルトとメモリコスト
- サイドチャネル攻撃に強い: Argon2i/Argon2id
2. 将来性がある
- 標準化されている: RFC 9106として標準化
- 広く採用されている: 多くのライブラリでサポート
- 継続的に改善: コミュニティによる監査
3. 調整可能
- 環境に応じて最適化: サーバーの性能に合わせて調整
- セキュリティとパフォーマンスのバランス: 用途に応じて設定
Argon2のデメリット
1. 計算コストが高い
MD5やSHA-1と比べて、計算時間が長いです。
MD5: 0.001秒
SHA-256: 0.001秒
Argon2: 0.5秒(推奨設定)
でも、これはセキュリティのための投資です。
2. メモリ使用量が多い
推奨設定で64MBのメモリを使用します。
大量のユーザーが同時にログインすると、メモリ使用量が増えます。
でも、現代のサーバーなら、問題ないレベルです。
3. 古いハッシュとの互換性がない
既存のシステムでMD5やSHA-1を使っている場合、移行が必要です。
既存ユーザーのパスワードを、次回ログイン時にArgon2で再ハッシュ化する必要があります。
2FA開発での活用
2FA開発では、セキュリティトークンのハッシュ化にArgon2を使いました。
従来の実装(SHA-256)
import hashlib
def hash_token(token):
return hashlib.sha256(token.encode()).hexdigest()
問題点:
- 高速すぎる: ブルートフォース攻撃が容易
- GPU攻撃に弱い: 並列化が簡単
Argon2での実装
from argon2 import PasswordHasher
ph = PasswordHasher(
time_cost=2,
memory_cost=65536,
parallelism=1
)
def hash_token(token):
return ph.hash(token)
def verify_token(hash, token):
try:
ph.verify(hash, token)
return True
except:
return False
改善点:
- セキュリティが向上: GPU攻撃に強い
- 将来性がある: 標準化されたアルゴリズム
- 調整可能: 環境に応じて最適化
まとめ
「MD5でいいでしょ」という考えは、完全に間違っていました。
パスワードのハッシュ化には、専用のアルゴリズムが必要です。
Argon2は、その最適解です。
重要なポイント
- MD5やSHA-1は使わない: パスワードハッシュ化には不適切
- Argon2idを推奨: バランスが取れた選択肢
- パラメータを調整: 環境に応じて最適化
- 継続的に監視: セキュリティは継続的な改善が必要
今後の展望
2FA開発では、Argon2を標準として採用しました。
今後は:
- 既存システムの移行: MD5/SHA-1からArgon2へ
- パラメータの最適化: サーバー環境に応じて調整
- セキュリティ監査: 定期的な見直し
セキュリティは、「これで大丈夫」という終わりがない分野です。
でも、Argon2を使うことで、正しい方向に進んでいることは確信できます。