「TOTP はわかるけど、HOTP は何が違うの?
どこで使われてるの?
どう動いて、どこが弱点?」そんな疑問を この記事ひとつで完全に解決します。
HOTP は古い規格ですが、今でも オフライン環境や工場設備、ハードウェアトークンなどで重要な役割を担っています。
1. HOTP とは?
HOTP(HMAC-Based One-Time Password) は
HMAC-SHA1 + カウンター を使ってワンタイムパスワードを生成する仕組み。
- RFC 4226 によって規格化
- TOTP の“兄”に相当
- 時刻を使わない → オフラインで強い
2. HOTP の特徴(ざっくり)
| 特徴 | 内容 |
|---|---|
| OTP が時間で失効しない | 使われるまで永遠に有効 |
| カウンター方式 | カウンター + Secret で計算 |
| オフライン動作 | 時刻同期不要 |
| 小型デバイス向け | ハードトークンでよく使われた |
| TOTP より弱い | 時限失効がないため攻撃耐性が低い |
3. なぜ HOTP が生まれたか(背景)
2000年代初期、認証デバイスの多くは:
- インターネット非接続
- 時計を持たない
- 電池寿命を伸ばしたい
- 計算能力が貧弱
こういう状況だったため、
軽くてオフラインでも動く HOTP が非常に便利だった。
4. HOTP の仕組み(内部ロジック)
計算式:
HOTP = Truncate(HMAC-SHA1(secret, counter)) mod 10^digits
- secret:Base32 の共有秘密鍵
- counter:0 → 1 → 2 … と進む
- digits:通常6桁
- HMAC-SHA1 は高速・軽量が理由で採用された
サーバー&認証器が同じ計算をして、値が一致すれば OK。
5. HOTP 登録フロー(Provisioning Flow)
ここを理解すれば HOTP の全体像がつかめる
登録時に secret をユーザーへ渡す必要がある。
そのために QRコードを使う。
登録フロー全体図
① サーバーが secret & counter=0 を生成
② otpauth:// URL を作成
③ それを QR コード化して画面に表示
④ ユーザーが Authenticator で QR をスキャン
⑤ Authenticator が secret と counter=0 を保存
⑥ 初回 OTP で同期確認 → counter=1 へ
ここでサーバーとユーザー側で
同じ secret と counter を共有する。
6. QR コードはどう理解されている?
中身は “otpauth:// URL” がそのまま入っている
QR の中身はこれ:
otpauth://hotp/Anna@example.com?
secret=JBSWY3DPEHPK3PXP&
issuer=ExampleApp&
counter=0&
digits=6
Authenticator アプリはこの URL を読み取り:
- secret
- counter
- issuer
- digits
を内部安全領域に保存。
QR 内の secret は暗号化されていない
ここが弱点:
盗撮されたら終わり。
7. HOTP の認証フロー
① Authenticator: HOTP(secret, counter=n) を生成
② User: OTP を入力
③ Server: 同じ secret & counter=n で HOTP を計算
④ 一致 → 認証成功
⑤ 両者 counter=n+1 に進める
サーバーは OTP を保存しているのではなく、
毎回計算で再現して照合している。
8. カウンター同期問題(HOTP の永遠のテーマ)
典型例:
Authenticator: counter=10
Server: counter=7
ユーザーが連打して OTP を連発生成すると
サーバーが追いつけず同期ズレが発生する。
解決法:Window(許容範囲)
server:
counter=7〜17 の範囲で OTP を検証
一致したら counter を更新して同期
Window を広げすぎると
ブルートフォースが成功しやすくなるので注意。
9. HOTP の脆弱性
OTP が失効しない(最大の弱点)
盗まれた OTP はいつでも使える。
Secret が平文のまま QR に含まれる
盗撮攻撃が強力。
DB が秘密鍵管理を抱える
DB漏えい → 全ユーザーの OTP を生成できる。
Window が攻撃を助長
対策で Window を広げるほど攻撃者も助かる。
10. 防御策
- Rate Limit(超重要)
- OTP 入力回数の制限
- アカウントロック
- Secret を KMS/Vault で暗号化
- QR コードは一度だけ表示
- Window を最小限にする(例:±5)
- “正しいパスワードの後にのみ OTP 入力”
- リバースプロキシでブルートフォース検出
- Secret をバックアップしない端末推奨
11. HOTP の使われる場所(現代版)
今でも HOTP は 限定的だけど重要な場面で現役。
① 銀行・金融のハードウェアトークン
オフライン、長寿命、時計なしの環境に最適。
② 企業の VPN・社内ネットワーク
Cisco / Juniper / Fortinet などの古い 2FA。
③ 工場・医療など“時刻同期禁止”の環境
NTP が使えない、時計がずれる設備に向く。
④ 安価 IoT / 組込みデバイス
時計(RTC)を載せられない端末など。
➡️ “時刻同期できない世界”で HOTP は強い。
12. TOTP との比較
| 項目 | HOTP | TOTP |
|---|---|---|
| 基準 | Counter | Time (30秒) |
| 有効期限 | 使われるまで不変 | すぐ失効 |
| セキュリティ | 弱い | 強い |
| 同期問題 | カウンタ同期問題 | 時刻同期 |
| 実用性 | 限定的 | 標準 |
| 用途 | ハードトークン、IoT | Webサービス、認証アプリ |
➡ 結論:一般ユーザー向けは TOTP 一択。
HOTP は特殊用途向け。
13. 実装例(Python)
import hmac, hashlib, struct, base64
def hotp(secret, counter, digits=6):
key = base64.b32decode(secret, casefold=True)
msg = struct.pack(">Q", counter)
h = hmac.new(key, msg, hashlib.sha1).digest()
o = h[-1] & 0x0f
binary = (struct.unpack(">I", h[o:o+4])[0] & 0x7fffffff)
return str(binary % (10 ** digits)).zfill(digits)
secret = "JBSWY3DPEHPK3PXP"
print(hotp(secret, 0))
print(hotp(secret, 1))
print(hotp(secret, 2))
まとめ
HOTP は「Secret + Counter」で同じ OTP を計算し合う仕組み。 オフラインに強いが、セキュリティの弱点から Web では TOTP / WebAuthn に置き換わった。