2 段階認証のワンタイムパスワードってよく使うけどどういう仕組みなの???

こんにちは。サーバーサイドエンジニアの伊藤です。

この記事は Enigmo Advent Calendar 2020 の 5 日目の記事です。

さっそくですが、みなさん 2 段階認証(2FA) のワンタイムパスワードの発行には何を利用していますか?

私は普段 Authy という 2 段階認証アプリを利用しています。ただ、AWSコマンドラインから操作する時などわざわざターミナルからアプリに移動してワンタイムパスワードをコピーして貼り付けるのが面倒だと思うことがありました。

ということで、OATHTOOLpeco を利用して CLI からワンタイムパスワード(TOTP)を取得するラッパーコマンドを作成しました。

今回は折角なので 2 段階認証(2FA) についてと 2 段階認証アプリで利用されるワンタイムパスワード(TOTP) についても調査したのでまとめました。

最後に作成したラッパーコマンドについて少しだけ紹介します。

Two-Factor Authentication(2FA)

そもそも、Two-Factor Authentication(2FA) とは何なのか?

ログインする際にユーザー名とパスワードに加えて、もう一つ追加の要素を要求する認証方法です。 万が一パスワードが漏洩した場合でも追加の要素を知らない限りログインすることができません。 これにより、セキュリティの強度を高めることが可能です。

一般的に追加の要素には下記の方法が用いられます。

  • Something you know(認証を行う本人のみが知る情報)
    • e.g. 認証番号(PIN)、パスワード、秘密の質問への回答 etc...
  • Something you have(認証を行う本人が所有するもの)
  • Something you are(認証を行う本人の身体的特徴)

みなさんご存知の AuthyGoogle Authenticator といったアプリはこの Something you have を用いた認証方法の一種です。 これらのアプリでは 2 つめの要素である Time-based One-Time Password(TOTP) を生成・取得することが可能です。

f:id:sean0628:20201128110604p:plain

HOTP vs. TOTP

ここででてきた Time-based One-Time Password(TOTP) とは何なのでしょうか? TOTP についてそのもととなる HMAC-based One-Time Password(HOTP) と合わせて説明していきます。

HOTP: HMAC-based One-Time Password (RFC 4226)

8-byte のカウンター(可変値)と秘密鍵をもとにワンタイムパスワードを生成します。 これらの情報をクライアント側とサーバー側で共有することで認証を行います。

HOTP を生成するためのアルゴリズムは下記のようになっております。 詳細は省きますが可変値であるカウンターと秘密鍵を HMAC に渡してその返り値を truncate することでワンタイムパスワードを生成します。

// Algorithm
C      8-byte counter value, the moving factor.  This counter
       MUST be synchronized between the HOTP generator (client)
       and the HOTP validator (server).

K      shared secret between client and server; each HOTP
       generator has a different and unique secret K.

HOTP(K,C) = Truncate(HMAC-SHA-1(K,C))

出典: HOTP: An HMAC-Based One-Time Password Algorithm

TOTP: Time-based One-Time Password (RFC 6238)

次は TOTP です。

下記のアルゴリズムからわかるように、TOTP のアルゴリズムの根本的部分は HOTP のものと同様です。唯一可変値であるカウンターの代わりに時間表現が用いられることが HOTP とは異なります。 時間表現と秘密鍵をクライアント側とサーバー側で共有しこれらをもとに発行したワンタイムパスワードを利用し認証を行います。

// Algorithm
X      represents the time step in seconds (default value X =
       30 seconds) and is a system parameter.

T0     is the Unix time to start counting time steps (default value is
       0, i.e., the Unix epoch) and is also a system parameter.

T = (Current Unix time - T0) / X
TOTP = HOTP(K, T)

出典: TOTP: Time-Based One-Time Password Algorithm

中身を見てみると HOTP も TOTP も想像よりはるかにシンプルだということがわかります。 アルゴリズム自体も簡単なものなので自前で実装してみるのも面白そうですね。

OATHTOOL ラッパーコマンド

さて、最後に少しだけ今回作成した CLI からワンタイムパスワード(TOTP)を取得する OATHTOOL のラッパーコマンドを紹介します。

Usage

$ mfa -h
usage: mfa [-h | --help] [-[no]-c | --[no]-copy] [-a <account>| --account <account>] [-l | --list]
  -v, --version                      Prints the version.
  -h, --help                         Prints this message.
  -[no]-c, --[no]-copy               Copies the generated token to the Clipboard.(default)
  -a <account>, --account <account>  Copies the generated token of <account> to the Clipboard.
  -l, --list                         Prints a list of available authenticator accounts.

基本的には peco を利用し、存在するアカウントから TOTP を取得したいアカウントを選択します。 -a|--account を利用することで TOTP を取得したいアカウントを明示的に指定することも可能です。

Demo

https://user-images.githubusercontent.com/35167423/96361564-bddfe900-1161-11eb-8371-d16c5be8469c.gif

Details

ラッパーコマンドの利用方法は下記をご覧ください。

github.com

最後まで読んでいただきありがとうございました。

明日の記事の担当はサーバーサイドエンジニアの橋本さんです。お楽しみに。

参考


株式会社エニグモ 正社員の求人一覧

hrmos.co