LoginSignup
3
4

More than 5 years have passed since last update.

多要素認証トークンをプログラムで取得してみる

Last updated at Posted at 2014-12-03

多要素認証の方式について

AWSやGoogleの多要素認証(MFA)に使われるTOTPについて書く。

昨今普及してきたワンタイムトークン(OTP)。これはちゃんと規格化されていて、ライブラリもあるので生成は難しくない。OTPにはシークレットとカウンタ値から発行するHOTPと、シークレットと時間から計算するTOTPがある。たいていはTOTPで、HOTPはあまり見たことがないが、たぶんサーバー側と時計を合わせるのが難しいようなものの場合に使うのだろう(昔は多かったかもしれない)。ちなみにTOTPは内部的にはLinuxエポックからの経過秒数/発行間隔(30秒とか)の数値をカウント値としてHOTPに投げるものだ。

つかってみる

是非はさておいて、AWSやGoogleの多要素認証のシークレットを取得すれば、それらの多要素認証のトークンを自分で発行することができる。AWSの場合はQRコードの下に折りたたみで隠して書いてある。Googleの方は確認してない。QRコードの場合はZXingなんかを使うと簡単にスクリーンショットからシークレットを取得することができる。

RubyならROTP、Pythonならpyotp、Node.jsではnotpというのがあるがだいたい似たようなものである。一点だけ気をつけるべきなのはBase32エンコードについてで、AWSやGoogleから供給されるものはBase32エンコードされている。ただ必ずそうなっているわけでもないらしくライブラリごとにbase32エンコードのまま受け入れるものや、エンコードとか考慮しないものとか、エンコードをオプションで指定するものなどがある。あと、nodeではthirty-twoっていうbase32のライブラリの0.0.1を使ってるものがいくつかあったけど、それはシークレットによっては正しく復号化できないで利用できない。ここにはまって数時間無駄にした。
0.0.2だと問題なくなっているので、以下のNode.jsのサンプルは0.0.2を利用する前提である。

サンプル

var qr = require('node-zxing')();
var notp = require('notp');
var base32 = require('thirty-two');

qr.decode("qr.png",function(err,out){
    var key = base32.decode(out.split(/=/)[1]);
    var token = notp.totp.gen(key);
    console.log(token);
});

スクリーンショットのQRコードからシークレットを取り出してトークンにすると上記のような感じになる。
ちなみにnode-zxingというのはZXingのnodeでのラッパーだけど、クラスパスの指定がコロンでハードコードされているのでWindowsでは動作しない。一応Pull requestを投げてみたけど、私の英語力とプロジェクトの放置されっぷりとかを見ると多分マージされないと思う。入れたあとに自分でWindowsならセミコロンにしたりすれば動く。一応私のフォークは以下である。

sashimizakana/node-zxing at windows-classpath-fix

というわけで

次回はやる気があれば、これをRaspberry Piに入れて7セグに出力するMFAデバイスを手作りする。
(まとまったネタになれば自分のサイトの方に載せます)

3
4
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
3
4