FIDO2/WebAuthn パフォーマンス分析
概要
FIDO2/WebAuthnは公開鍵暗号を使用するため、パスワード認証と比較して異なるパフォーマンス特性を持ちます。本ドキュメントでは、FIDO2認証のパフォーマンス特性、CPU負荷の要因、最適化手法について解説します。
FIDO2認証フローとCPU負荷
認証フローの構成
┌─────────────────────────────────────────────────────────────────────┐
│ FIDO2認証フロー │
├─────────────────────────────────────────────────────────────────────┤
│ 1. Challenge Request → ランダムチャレンジ生成 │
│ 2. Assertion Generation → クライアント側ECDSA署名(軽量) │
│ 3. Authentication Verify → サーバー側ECDSA署名検証(CPU負荷高) │
└─────────────────────────────────────────────────────────────────────┘
CPU負荷が高い処理
1. ECDSA署名検証(最もCPU負荷が高い)
サーバー側で行われるECDSA署名検証が、FIDO2認証で最もCPU負荷が高い処理です。
クライアント サーバー
│ │
│ assertion(署名付き) │
│ ─────────────────────────────────→ │
│ │
│ ┌─────────┴─────────┐
│ │ ECDSA署名検証 │
│ │ - P-256曲線 │
│ │ - 楕円曲線点乗算 │
│ │ - 計算コスト高 │
│ └─────────┬─────────┘
│ │
│ 認証結果 │
│ ←───────────────────────────────── │
処理内容:
- クライアントから送信されたアサーションの署名を検証
- P-256(secp256r1)曲線でのECDSA検証
- 楕円曲線上の点乗算が必要で計算コストが高い
2. チャレンジ生成
// SecureRandomによる32バイトのランダム生成
byte[] challenge = new byte[32];
secureRandom.nextBytes(challenge);
処理内容:
- 暗号学的に安全なランダムバイト生成
- エントロピープール枯渇時に遅延する可能性
3. CBOR/JSONパース
処理内容:
- クライアントからのJSON/CBORデータのパース
- AuthenticatorDataのデコード
- Base64URLエンコード/デコード
高負荷時の挙動
リクエストキューイング
サーバーの処理能力を超えるリクエストが来ると、キューイングが発生します。
┌─────────────────────────────────────────────────────────────────────┐
│ Webアプリケーションサーバー │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ リクエスト → [接続キュー] → [ワーカープール] → [アプリケーション処理] │
│ ↑ ↑ │
│ キュー上限 ワーカー数上限 │
│ │
│ ワーカーが全てビジー → キューで待機 → レイテンシ増加 │
│ キューも満杯 → 接続拒否(503等) │
│ │
└─────────────────────────────────────────────────────────────────────┘
一般的な構成要素:
| 要素 | 説明 |
|---|---|
| 接続キュー | ワーカーが空くまでリクエストを待機させる |
| ワーカープール | 同 時に処理できるリクエスト数の上限 |
| タイムアウト | キュー待ち時間の上限 |
挙動:
- リクエスト到着時、空きワーカーがあれば即座に処理開始
- 全ワーカーがビジーの場合、接続キューで待機
- キューも満杯になると接続拒否またはタイムアウト
Little's Law
L = λ × W
L: システム内の平均リクエスト数
λ: スループット(req/sec)
W: 平均レイテンシ
スループットが飽和すると、同時リクエスト数の増加分だけレイテンシが増加します。
全ステップが均等に遅くなる現象
高負荷時に「FIDO2検証だけでなく全ステップが遅くなる」場合、それはFIDO2固有の問題ではなく、サーバー全体のCPU飽和によるキューイングが原因です。
他の認証方式との比較
パスワード認証との比較
| 項目 | パスワード認証 | FIDO2認証 |
|---|---|---|
| サーバー側処理 | bcrypt/Argon2ハッシュ比較 | ECDSA署名検証 |
| CPU負荷特性 | 意図的に重くしている | 暗号処理として必要な負荷 |
| 調整可能性 | コストファクターで調整可 | 固定(アルゴリズム依存) |
| スケール特性 | ハッシュ計算がボ トルネック | 署名検証がボトルネック |
注意: bcryptのコストファクター設定によっては、パスワード認証の方が重い場合もあります。
最適化手法
1. 水平スケーリング
FIDO2認証はステートレスなため、インスタンス追加で線形にスケール可能です。
# docker-compose.yml
services:
idp-server:
deploy:
replicas: 4 # インスタンス数を増加
2. WebAuthnManagerのシングルトン化
リクエストごとにWebAuthnManagerを生成している場合、シングルトン化で初期化コストを削減できます。
// 毎回生成(非効率)
public void authenticate(...) {
WebAuthnManager manager = WebAuthnManager.createNonStrictWebAuthnManager();
}
// シングルトン化(効率的)
private static final WebAuthnManager MANAGER =
WebAuthnManager.createNonStrictWebAuthnManager();
3. 非同期処理の活用
クリティカルパスにない処理を非同期化:
- 監査ログの記録
- 統計情報の更新
- セキュリティイベントの発行
@Async
public void recordAuditLog(AuthenticationEvent event) {
// 非同期で監査ログを記録
}
4. コネクションプール最適化
データベースコネクションプールを適切に設定:
spring:
datasource:
hikari:
maximum-pool-size: 20
minimum-idle: 10
5. ハードウェア最適化
- CPU: 十分なコア数の確保
- AES-NI: 暗号処理のハードウェアアクセラレーション
- エントロピー:
/dev/urandomの使用(Linuxの場合)
ボトルネック特定方法
1. リソースモニタリング
# Docker環境の場合
docker stats
確認項目:
- CPU使用率が80%を超えていないか
- メモリ不足が発生していないか
2. PostgreSQLクエリ分析
-- pg_stat_statements拡張を有効化
CREATE EXTENSION pg_stat_statements;
-- 統計リセット
SELECT pg_stat_statements_reset();
-- テスト実行後、遅いクエリを確認
SELECT
LEFT(query, 80) as query_preview,
calls,
ROUND(mean_exec_time::numeric, 2) as avg_ms,
ROUND((total_exec_time / SUM(total_exec_time) OVER() * 100)::numeric, 1) as pct
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 10;