簡単に言うと
TOTPはTime-Based One-Time Password(時間ベースワンタイムパスワード)の略です。Google AuthenticatorやAuthyなどのアプリが、ログイン時に入力する6桁のコードを生成している仕組みです。各コードは30秒間有効で、それが過ぎると新しいコードに置き換わります。
これが基本的な仕組みです。しかし、実際の内部動作は驚くほどシンプルです。
秘密鍵と時計
TOTPには2つの要素が必要です:秘密鍵と現在時刻です。
ウェブサイトで二要素認証を設定すると、サイトはランダムな秘密鍵を生成し、通常はQRコードとして共有します。認証アプリがコードをスキャンして鍵を保存します。ウェブサイトも同様に鍵を保存します。この最初の交換が済めば、秘密鍵は二度と送信されることはありません。
ここが面白い部分です。認証アプリもウェブサイトのサーバーも、どちらも時計を持っています。両者は現在時刻を知っています。そのため、秘密鍵と現在時刻を独立して組み合わせ、同じ計算を実行し、同じ6桁のコードを得ることができます。通信は不要です。
ログインフォームにコードを入力すると、サーバーは同じ秘密鍵と現在時刻を使って独自のコードを生成し、一致するか確認します。一致すれば、ログイン成功です。
計算の仕組み
暗号理論を理解しなくてもTOTPは使えますが、興味がある方のために概要を説明します。
現在時刻は30秒間隔に分割されます。現在、「1970年1月1日から何個の30秒ブロックが経過したか」を表す数字があります(これはUnixエポックと呼ばれ、コンピューターでよく使われる基準時刻です)。この数字をタイムステップと呼びます。
アルゴリズムは秘密鍵とタイムステップをHMAC-SHA1に入力します。HMAC-SHA1は一方向ハッシュ関数です。出力は長いバイト列です。TOTPは出力の一部を取り出し、数字に変換し、最後の6桁を取得します。これがあなたのコードです。
タイムステップは30秒ごとに変わるため、コードも変わります。また、ハッシュ関数は一方向性のため、コードを見た人がそこから秘密鍵を逆算することはできません。
コードが期限切れになる理由
30秒のウィンドウはトレードオフです。短ければより安全になりますが、長ければ入力時間が増えます。30秒はRFC 6238(TOTPを定義する仕様書)で合理的なデフォルトとして定められました。
多くのサーバーは、デバイスとサーバーの時刻ずれに対応するため、前後の30秒ウィンドウのコードも受け入れます。実際には約90秒の猶予があります。
コードが期限切れになると、それは無価値になります。傍目で画面を見た人が見たものを悪用できる時間は非常に限られており、多くのサービスは既に使用されたコードを拒否します。
RFC 6238:標準規格
TOTPは独自仕様ではありません。IETF(Internet Engineering Task Force)が2011年に公開したRFC 6238で定義されています。この仕様は、HOTP(RFC 4226)と呼ばれる以前の標準規格を発展させたものです。HOTPはカウンターを使いますが、TOTPはそれをタイムステップに置き換えただけです。
これはオープン標準なので、どの認証アプリもTOTPに対応するサービス向けにコードを生成できます。特定のベンダーに縛られることはありません。Google Authenticator、Authy、1Password、Bitwarden、その他数十のアプリはすべて同じアルゴリズムを使用しています。
TOTPと通常のパスワードの比較
通常のパスワードは静的です。毎回ログインする際に同じ文字列です。データ侵害、フィッシング、マルウェアなどで誰かに盗まれると、変更するまで何度も使われる可能性があります。
TOTPコードはいくつかの点で異なります:
- 30秒ごとに変わるため、盗まれたコードは短い間しか使えません
- 設定後に秘密鍵がデバイスから離れることがないため、安全です
- 従来の方法ではフィッシングされにくく、攻撃者が使おうとする頃には期限切れになっている可能性があります
- 複雑なものを作成して記憶する必要がない
ただし、TOTPはパスワードの代替ではありません。追加のレイヤーです。パスワード(あなたが知っているもの)は依然必要で、TOTPコードはあなたが秘密鍵を持つデバイスにアクセスできること(あなたが持っているもの)を証明します。
実用的な側面
TOTPの設定は通常、アカウントあたり約1分で完了します。サービスがQRコードを表示し、認証アプリでスキャンし、コードを入力して確認します。これだけです。
その後のログインは約10秒追加でかかります。認証アプリを開き、正しいアカウントを探し、コードを読み、入力します。これは小さな摩擦ですが、アカウントの侵入を劇的に困難にします。
認証アプリへのアクセスを失うことを心配する人もいます。それは正当な懸念です。多くのサービスは設定時にバックアップコードを提供します。それらを安全な場所に保存してください。クラウドバックアップをサポートする認証アプリや、パスワードマネージャーに秘密鍵を保存する方法もあります。
実際に試してみる
何かをコミットせずにTOTPを試したい場合は、2fa.zipでコードを生成できます。完全にブラウザ内で動作し、秘密鍵はどのサーバーにも送信されないため、実際のアカウントで2FAを設定する前にコードの仕組みを感じるのに最適です。