LoginSignup
2
2

More than 5 years have passed since last update.

time-based HOTPと言ってはいけない

Last updated at Posted at 2013-11-19

前回の記事はこちら 小ネタ: 2段階認証でssh

おさらいをすると、LinuxのPAMモジュールの一つとしてOATH認証 (Google Authenticatorとかで使われるアレ)を追加することができるのでsshで使ってみた、という話です。2段階認証がご家庭に届くまであと30進捗くらいです。

で、そこで使った(PAM認証の)pam_oathにしろ、(Apacheの)mod_authn_otpにしろ、usersfileと呼ばれるファイルを使います。これについてはきちんとした名称も仕様っぽいものはないんですが (OATHの範囲でもないようですし)、参考になる資料として以下があります。

(なお、以降私の中ではこの設定ファイルの名称を"usersfile"とすることにしました。根拠は、以下のwikiページと、あと後述するpam_oathの実装で使われているファイル名)

#       HOTP/T30        - HOTP time-based token with 30 second interval and six digit OTP
#       HOTP/T60        - HOTP time-based token with 60 second interval and six digit OTP
#       HOTP/T60/5      - HOTP time-based token with 60 second interval and five digit OTP

ああん?? HOTP time-based ってなんだよ??? (逆切れ

HOTP/T30 等はTOTPのはず……。もっとも、ここで素直にTOTPと書かない奥ゆかしさには頭が沸騰します。

参考まで、最初のプロトコルタイプに対応するpam_oath側 (liboath)の実装を拾って来ました (oath-toolkit-2.4.0)

liboath/usersfile.c
static int
parse_type (const char *str, unsigned *digits, unsigned *totpstepsize)
{
  *totpstepsize = 0;
  if (strcmp (str, "HOTP/E/6") == 0
      || strcmp (str, "HOTP/E") == 0 || strcmp (str, "HOTP") == 0)
    *digits = 6;
  else if (strcmp (str, "HOTP/E/7") == 0)
    *digits = 7;
  else if (strcmp (str, "HOTP/E/8") == 0)
    *digits = 8;
  else if (strncmp (str, "HOTP/T30", 8) == 0)
    {
      *totpstepsize = 30;
      if (strcmp (str, "HOTP/T30") == 0 || strcmp (str, "HOTP/T30/6") == 0)
        *digits = 6;
      else if (strcmp (str, "HOTP/T30/7") == 0)
        *digits = 7;
      else if (strcmp (str, "HOTP/T30/8") == 0)
        *digits = 8;
      else
        return -1;
    }
  else if (strncmp (str, "HOTP/T60", 8) == 0)
    {
      *totpstepsize = 60;
      if (strcmp (str, "HOTP/T60") == 0 || strcmp (str, "HOTP/T60/6") == 0)
        *digits = 6;
      else if (strcmp (str, "HOTP/T60/7") == 0)
        *digits = 7;
      else if (strcmp (str, "HOTP/T60/8") == 0)
        *digits = 8;
      else
        return -1;
    }
  else
    return -1;

  return 0;
}

"TOTP"というタイプは許さないのですが、HOTP/T30等をいみじくもtotpstepsizeという変数等で扱ってるのです。紛らわしい。いやでもこのあまりに実直な実装には安心しました。ガチパーサでも使ってないかドキドキしてたのです。

そもそもHOTPと時間ベース拡張がTOTPで、HOTP自体はHMAC OTPという以上ではないようなのです。

おまけですが、usersfileのタイプ指定において既にpam_oathとmod_authn_otpで実装のズレがあるのが分かります。HOTP/T30/5 (30秒サイクルのTOTPで入力する数字は5桁、を意図)はmod_authn_otpでしか受け付けません。

ただ、手元でGoogle Authenticatorで時間ベースの設定(HOTP/T30)を使っている範囲において、両者は同じusersfileの設定行を受け付けました。つまり、1回登録して二箇所で使えます。(試行回数も1回ですけどネ)

これが何が嬉しいかというと、普通の人にはほとんど何も嬉しくありません。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2