ワンタイムパスワード (OTP)
ワンタイムパスワード (OTP) は、ワンタイム PIN やワンタイム認証コード (OTAC) とも呼ばれ、1 回のログイン試行ごとに生成される単一のコードです。ウェブサイトがメールなどの別の経路を通じてユーザーにコードを送信するか、あるいはユーザーの端末が独自にコードを生成します。その後、ユーザーはそのコードをサイトに入力してログインします。
概要
ワンタイムパスワードを用いた認証フローは、ユーザーが「知っているもの」(パスワード)や「本人であること」(指紋などの生体認証情報)ではなく、「持っているもの」(携帯電話、メールアドレス、認証器に格納された秘密など)に基づいています。
ワンタイムパスワードは、従来のパスワードに加えて使用することも、従来のパスワードを置き換えるものとして使用することもできます。多くの場合、支払いを行う際など、ユーザーの意図を確認するために使用されます。
多くの OTP は 6 桁で構成されており、正解する確率は 100 万分の 1 です。これは、組み合わせがわずか 1 万通りしかない 4 桁の OTP よりもはるかに優れています。OTP が依存しているセキュリティの仕組みは、その「一時性」にあります。OTP は通常、定義された時間枠内でのみ有効であり、使用後は無効になります。そのため、OTP の有効期限は短く設定されています(理想的には 5 分以内、より強力な保護を求める場合は 30~120 秒です)。
この記事では、ワンタイムパスワードの 3 つの一般的な実装方法、すなわち電子メール、SMS、および時間ベースのワンタイムパスワード (TOTP) について解説します。この比較において、TOTP は最も安全な配信手段と考えられます。
メール OTP
メールベースの OTP では、登録時に次のことを行います。
- ユーザーはウェブサイトにメールアドレスを提供します。
- ウェブサイトでは、このメールアドレスにアクセスする権限を保有していることを確認します。
ユーザーがログインを要求した場合は、次のようにします。
- ウェブサイトがワンタイムコードを生成し、ユーザーにメールで送信します。
- ユーザーがウェブサイト上でそのコードを入力します。
- ウェブサイトがユーザーをログインさせます。
コードを配信するには、主に 2 つの手法があります。
-
ウェブサイトは、ユーザーのメールアドレスに個別のワンタイムリンクを送信します。ユーザーがリンクをクリックすると、ウェブサイトはユーザーを認証します。このリンクは数分間のみ有効で、ユーザーがクリックした直後に失効します。この方法はユーザーにとても便利ですが、同じ端末かつ同じブラウザーで手続きを完了させる必要があります。そのため、アプリ内のブラウザーや別の端末からログインする場合、課題となる可能性があります。同時に、メール内のリンクをクリックするようユーザーに依頼することは、フィッシング攻撃に対するユーザーの脆弱性を高めることにもなります。
-
ウェブサイトは、ユーザーのメールアドレスに個別のワンタイムコードを送信します。その後、ユーザーは任意の端末とブラウザーで、そのコードをウェブサイトに入力するよう依頼されます。この手順は、ユーザーにとって時間がかかり、不便に感じられることもありますが、ログイン場所の選択肢が広がるという利点があり、メール内のリンクを使用するよりも安全であると考えられています。
すべてのメールベースの OTP 方式において良好な使い勝手を実現するためには、ユーザーが OTP メールを適度にすばやく受け取れることが重要です。
SMS OTP
SMS OTP では、ユーザーは登録時に携帯電話番号を指定し、ログイン時にウェブサイトからその携帯電話へ SMS メッセージでワンタイムコードが送信されます。
電子メールと SMS の両方の方法における弱点は、攻撃者がコードを含むメッセージに介入可能であることです。しかし、SMS の方がより脆弱であると考えられています。
- SMS メッセージは A5/X ストリーム暗号を使用して暗号化できますが、この暗号にはさまざまな脆弱性が確認されており、メッセージは数分あるいは数秒で復号されてしまいます。
- SMS のルーティングプロトコル(SS7)には既知の欠陥があり、攻撃者がテキストメッセージを自分たちの方へ転送できてしまう原因となっています。
- SIMスワップ詐欺では、攻撃者は携帯電話番号ポータビリティ(通常、通信事業者の乗り換えや、携帯電話の紛失・盗難の際に使用されている機能)を悪用し、被害者になりすまします。
- 通信事業者は、アカウントが閉じられた後、その電話番号を新しいユーザーに再割り当てすることも可能です。
また、旅行中に別の SIM カードや eSIM を使用している場合、コスト削減のために普段使っている SIM カードや SMS サービスを無効にしている可能性があります。その場合、SMS で送信されるワンタイムパスワードを受け取ることができません。
そのため、SMS による OTP を単独で、新しいセッションの確立や一般的な認証に使用すべきではありません。もし使用するとしても、第二の認証要素として、あるいは意図の確認(例:支払い)のためにのみ使用してください。
SMS コードの自動入力
ユーザーがサイト上で SMS コードを簡単に入力できるようにし、フィッシング攻撃のリスクを縮小するため、SMS 経由で配信されるオリジン限定のワンタイムコードに関する標準により、ウェブサイトはワンタイムコードの値に対して自動入力機能に対応することができます。
これを有効にするには、SMS メッセージを次のように書式化する必要があります。
Your verification code is 123456. @www.example.com #123456
次に、サイトのログインフォームに、autocomplete=one-time-code という属性値が設定された <input> 要素を提供してください。
<form action="/verify-otp" method="POST">
<input
required
type="text"
autocomplete="one-time-code"
inputmode="numeric"
maxlength="6"
pattern="\d{6}" />
<input type="submit" />
</form>
ブラウザーは SMS からコードを自動的に抽出します。メッセージに指定された送信元がログインフォームの送信元と一致する場合、<input> 要素にそのコードが自動入力されます。
WebOTP API
WebOTP API を使用すると、ウェブサイトは SMS で配信されるワンタイムコードにプログラムからアクセスできるようになります。ただし、この API はブラウザー間の対応状況が十分ではありません。また、コードへのプログラムによるアクセスが必要でない限り、この API を使用する必要はありません。標準化された書式化と autocomplete=one-time-code を使用すれば、ブラウザーを問わず自動入力機能が動作するはずです。
TOTP
時間ベースのワンタイムパスワードでは、ウェブサイト側がユーザーにログインコードを送信することはありません。代わりに、ウェブサイトとユーザーは、現在の時刻と共有秘密に基づいて、互いに独立して同じコードを生成します。コードを生成するには、ユーザーは自分の端末にアプリをインストールしなければなりません。これを「認証アプリ」と呼びます。
登録時に次のようにします。
-
ユーザーは、まだ認証器を所持していない場合、それをインストールします。
-
ウェブサイトは次のようにします。
- 共有秘密を生成します。
- 秘密をユーザーのアカウントに関連付けて、安全に格納します。
- 秘密と関連するメタデータを、
otpauthURI に埋め込みます。 - URI を QR コードとしてエンコードし、ユーザーにスキャンするよう促します。
-
ユーザーの端末上の認証器は、QR コードから URI をデコードし、その URI を構文解析して、シークレットおよび関連するメタデータを格納します。
ログイン時、ユーザーは現在のコード値を指定します。このコード値は、認証器が秘密と現在の時刻に基づいて計算されたものです。ウェブサイト側でも同様の計算を行うことができ、両者の値が一致すれば、ユーザーはログインできます。
TOTP アルゴリズム
時間ベースのワンタイムパスワード (TOTP) アルゴリズムは、RFC 6238 で規定されています。これは、RFC 4226 で指定されている HMAC ベースのワンタイムパスワードアルゴリズム (HOTP) の拡張版です。
このアルゴリズムは、6 桁のワンタイムコードを生成し、その有効期間は制限されています(通常は 30 秒間です)。つまり、これまでに説明した他の OTP システムとは異なり、TOTP は設計上、時間ベースの有効期限と自動無効化機能を実装しているということです。
秘密鍵は、160 ビット以上の長さであるランダムな値であることが推奨されます。
TOTP を実装する際には、Python 用の pyotp や Node 用の otpauth など、定評のあるサードパーティー製パッケージを使用しましょう。
otpauth URI 形式
otpauth URI 形式は、この IETF 草案 で定義されています。
TOTP の場合、URI は次のように書式化します。
otpauth://totp/LABEL?secret=MQCHJLS6FJXT2BGQJ6QMG3WCAVUC2HJZ&issuer=My_Website
LABEL 要素はユーザーを識別します。例えば、ユーザー名などが該当します。
URI にはいくつかのクエリー文字列の引数が含まれていますが、その中でも最も重要なものは以下の通りです:
認証アプリ
TOTP に対応している認証アプリは、商用・オープンソースを問わず数多く存在します。例えば、Ente Auth、2FAS、Microsoft Authenticator などが挙げられます。
秘密の保護
TOTPでは、秘密鍵をサーバーとクライアントの両方に安全に格納しなければなりません。
サーバーに関しては、パスワードの保存の場合と同様の考慮事項があります。つまり、サーバーは、たとえ攻撃者がサーバーのデータベースを取得できたとしても、TOTP の秘密鍵にアクセスできないような方法で格納しなければなりません。
クライアントにとって、認証器は秘密をある程度保護する機能を提供する必要があります。
長所と短所
パスワードと比較して、OTP の最大の強みは、ユーザーが秘密鍵の作成や記憶に関与しない点にあり、 そのため、OTP は推測やクレデンシャルスタッフィング攻撃に対して脆弱ではありません。
短所
-
SMS やメールによる OTP には、攻撃者がサーバーから送信された OTP コードに介入してしまうリスクがあり、この点において SMS はメールよりもはるかに脆弱です。
-
TOTP は傍受のリスクはありませんが、攻撃者が共有秘密を取得してしまうリスクが追加されます。
-
あらゆる形態の OTP は、フィッシング攻撃に対して脆弱です。
セキュリティの問題はさておき、OTP には使い勝手の面でいくつかの課題があります。
- SMS やメールによる OTP は、コードを送信するサーバーとそれを受け取るユーザーとの間に大きな遅延が生まれる場合、使い勝手が悪くなることがあります。
- TOTP の場合、認証器をインストールする必要があることが、登録の大きな障壁となっています。しかし、もちろん、ユーザーがすでに別のサイト用にその認証器をインストールしている場合は、サイトに登録する際に改めてインストールする必要はありません。
OTP の推奨事項
OTP、特に TOTP は、追加の認証要素として、また支払いを行う際など、ユーザーの意図を確認する手段として有益です。一般的な認証目的では、フィッシング攻撃に対する耐性が高いパスキーを使用した方が向いています。
OTP を実装する場合は、以下の推奨事項を考えてみることを検討してみてください。
- メールや SMS を利用した OTP よりも TOTP を推奨し、特に SMS を利用した OTP は避けましょう。
- TOTP を使用する場合は次のようにします。
- 信頼できるライブラリーを使用して、秘密や OTP コードを生成してください
- 秘密鍵をサーバーに安全に格納してください