こんにちは、2024年度に新卒で入社しました。株式会社ROBOT PAYMENTの片岡です。
以前は開発者用のリファレンス作成を中心に行っていましたが、今は開発を行っております。
今回は、開発をしていく中でワンタイムパスワードについて調べる機会がありましたので、ワンタイムパスワードの理解を深める意味も込めてご紹介します。
はじめに
近年、サービスを利用する際にワンタイムパスワードで認証を行うことが多くなってきたのではないでしょうか?私自身、様々なサービスにおいてワンタイムパスワードを使用した多要素認証が増えてきたと実感しております。
実際にワンタイムパスワードを扱う際は以下の流れを何も考えずに行っています。
- ワンタイムパスワードが発行されるまで待ち
- 発行されたワンタイムパスワードを入力
- 認証する
機能自体がシンプルなこともあり認証までの流れもスムーズで万人が使用できるシステムになっていると思います。 そんなワンタイムパスワードを調べましたが、想定よりも複雑でした。。。
そもそもワンタイムパスワードとは?
調べた内容からワンタイムパスワードの定義をまとめると以下になります。
”1度だけあるいは、短期間だけ利用可能なパスワードのこと”
シンプル!
シンプルな定義かつワンタイムパスワードの定義は広いと感じました。
普段見る半角数字のワンタイムパスワードがワンタイムパスワードたるものだと考えていましたが、上記の定義を満たしていれば数字だけでなく画像や音声もワンタイムパスワードになることがわかりました!
その中でも今回は、数字のみのワンタイムパスワードに着目して調査をしました。
2種類のワンタイムパスワード
調査の結果ワンタイムパスワードは以下の2種類あることがわかりました。
- HOTP(Hash-based Message Authentication Code One-Time Password)
- TOTP(Time-based One-Time Password)
ハッシュベースのワンタイムパスワードと時間ベースのワンタイムパスワードという違いはあるものの、結果的には同じようにランダムな数字が出力されます。 そのため、数字のワンタイムパスワードを発行するには、ハッシュを元に時間制限があるランダムな数字を発行できれば良いと考えていましたが、なんととアルゴリズム要件まで定義されていました。。。
各ワンタイムパスワードの要件
HOTP(Hash-based Message Authentication Code One-Time Password)
HOTPはハッシュ(HMAC)ベースのワンタイムパスワードで、時間による失効はなくユーザーが認証サーバーで検証されるまで有効となります。
アルゴリズム要件
- アルゴリズムはシーケンスベースまたはカウンターベースでなければならない(MUST)
- ハードウェアの要件を最小限に抑えることにより経済的であるべき(SHOULD)
- アルゴリズムは数値入力をサポートしないトークンとサポートするデバイスの両者で使用可能でなければならない(MUST)
- 値はユーザーが簡単に読み取り入力できるものではならなく、HOTPの値は少なくとも6桁の値でなければならない(MUST)
- ユーザーフレンドリーなカウンタ再同期のメカニズムでなければならない(MUST)
- アルゴリズムは強力な共有秘密を使用しなければならなく少なくとも128ビット。(MUST)
この要件と参考資料を踏まえてHOTPを計算するコード (C#)は以下になります。
public static string CalculateHOTP(byte[] hash) { var offset = hash[19] & 0x0F; var binary = (hash[offset] & 0x7F) << 24 | (hash[offset + 1] & 0xFF) << 16 | (hash[offset + 2] & 0xFF) << 8 | (hash[offset + 3] & 0xFF); var otp = binary % 1000000; return otp.ToString("D6"); }
このアルゴリズムによりハッシュから6桁のワンタイムパスワードを発行できます。
TOTP(Time-based One-Time Password)
TOTPは時間ベースのワンタイムパスワードで、時間により失効します。また、各ワンタイムパスワードが有効な時間はタイムステップと呼ばれ、長さは30秒から60秒が一般的とされています。
アルゴリズム要件
- 証明者と検証者はOTP生成のため、現在のUnix時間を知っているか導出できなければならない(MUST)
- 証明者と検証者は共有秘密を生成するために、同じ秘密変換の知識を共有しなければならない(MUST)
- アルゴリズムはHOTPを主要なビルディングブロックとして使用しなければならない(MUST)
- 証明者と検証者は同じタイムステップ値Xを使用しなければならない(MUST)
- 各証明者には一意の秘密鍵が必要(MUST)
- 鍵はランダムに生成するか、鍵導出アルゴリズムを使用して導出する必要がある(SHOULD)
- 鍵は改ざん防止装置に格納される場合があり、不正なアクセスや使用から保護する必要がある(SHOULD)
この要件と参考資料を踏まえてTOTPのタイムステップ数を計算するコード(C#)は以下になります。
public static long TimeSteps(int x) { // (Current Unix time - T0) var unixTimestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); return unixTimestamp / x; }
上記のタイムステップと秘密鍵を組み合わせHOTPのアルゴリズムを使用することにより、ワンタイムパスワードを発行できます。
ここまで2種類のワンタイムパスワードとそのアルゴリズム要件を中心にご紹介しましたが、考慮すべきセキュリティ問題などがまだまだあります。(ブルートフォース攻撃等) 長くなりましたが、気になる方はセキュリティに関する部分も是非調べてみてはいかがでしょうか。
まとめ
普段何気なく使用しているワンタイムパスワードを調べてみると「ただランダムな数字を発行しているだけ」と考えていた自分が恥ずかしくなるくらいには奥が深かったです。しかし、調べていくにつれて段々と理解を深めることができました。
これからも学び続け成長していけるように頑張りたいと思います。
We are hiring!!
ROBOT PAYMENTでは一緒に働く仲間を募集しています!!!