LoginSignup
8
6

More than 5 years have passed since last update.

ErlangでOATHなワンタイムパスワードライブラリ"POT"をElixir から使う

Posted at

概要

  • Erlangでワンタイムパスワードを生成するライブラリがあるのでElixirから使ってみた
  • githubにざっとドキュメントはあるが、実際に動作確認してみたメモ

動作メモ

HOTP生成

# secretはencodeしたものを渡す必要がある
iex(1)> raw_secret = "1234567890"
"1234567890"
iex(2)> encoded_secret = Base.encode32(raw_secret, padding: false)
"GEZDGNBVGY3TQOJQ"
iex(3)> counter = 1
1
iex(4)> :pot.hotp(encoded_secret, counter)
"263420"

# 桁を指定することも可能
iex(5)> :pot.hotp(encoded_secret, counter, token_length: 8)
"13263420"

# base32 で encode されていない secret を指定するとエラー
iex(6)> encoded_secret = "1234567890"
"1234567890"
iex(7)> :pot.hotp(encoded_secret, counter)
** (FunctionClauseError) no function clause matching in :base32.std_dec/1
   ...

ソースコードを見ると、digest method を指定することもできる模様。
crypt.hmac を使っているので、 http://erlang.org/doc/man/crypto.html にある
md5, ripemd160, sha, sha224, sha256, sha384, sha512 あたりが使えそうだが、うまく動かなかったので未確認。

HOTP検証

iex(1)> encoded_secret = "GEZDGNBVGY3TQOJQ"
"GEZDGNBVGY3TQOJQ"
iex(2)> counter = 1
1
iex(3)> token = token = :pot.hotp(encoded_secret, counter)
"263420"
# :last として最後に検証したカウンタの値を指定
iex(4)> :pot.valid_hotp(token, encoded_secret, [{:last, counter - 1}])
1

# 戻り値はカウンタの値
iex(5)> counter = 3
3
iex(6)> token = token = :pot.hotp(encoded_secret, counter)
"626604"
iex(7)> :pot.valid_hotp(token, encoded_secret, [{:last, counter - 1}])
3

# 検証に失敗したら false 
iex(8)> invalid_token = "000000"
"000000"
iex(9)> :pot.valid_hotp(invalid_token, encoded_secret, [{:last, counter - 1}])
false

TOTP作成

# encode secret を渡すと、現在時刻でTOTP生成
iex(1)> encoded_secret = "GEZDGNBVGY3TQOJQ"
"GEZDGNBVGY3TQOJQ"
iex(2)> :pot.totp(encoded_secret)
"508549"

# interval_length を指定することが可能
iex(3)> :pot.totp(encoded_secret)
"836210"
## デフォルトは30秒
iex(4)> :pot.totp(encoded_secret, interval_length: 30)
"836210"
iex(5)> :pot.totp(encoded_secret, interval_length: 60)
"136108"

HOTPで指定できるパラメータはTOTPでも指定可能。
interval_length は指定できるのに時刻のタイムスタンプを指定できない。
自分でやろうと思ったら、タイムスタンプを interval_length で割った値を counter として HOTP 生成すれば可能。

TOTP検証

# encode secret を渡すと、現在時刻でTOTP生成
iex(1)> encoded_secret = "GEZDGNBVGY3TQOJQ"
"GEZDGNBVGY3TQOJQ"
iex(2)> token = :pot.totp(encoded_secret)
"363352"

# TOTPの検証成功時は true
iex(3)> :pot.valid_totp(token, encoded_secret)
true

感想

  • HOTP/TOTPの生成/検証はほぼドキュメント通り一通りできる
  • TOTPでタイムスタンプを指定できないのだけちょっとだけ不満

不満なところのパラメータを指定できるようにしたライブラリを自分で書いているので、いい感じになったら追記予定。

8
6
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
8
6