pslaboが試したことの記録

はてなダイヤリーからはてなブログに引っ越してきました

この日記は現在実行中の減量記録を含む個人的なメモとして始めましたが、最近はコンピュータやガジェット、ハック、セキュリティネタのほうがメインになっております。

はてなダイヤリー時代はカテゴリ分けが適当だったのですが、これはそのうち直します。


2段階認証のパスコード生成方法をperlの実装で読んでみる

2段階認証のパスコード生成処理をちょいと試してみようと思っていたら、
GitHubにこういうのが上がっていたので読んでみる。

GitHub - j256/perl-two-factor-auth: Two Factor Authentication Perl code


そうすると、パスコード生成は2つの要素、base32Secret の値と30秒毎の現在時刻のpaddingの値だけで行われていることが良く分かりました。これを行っているのは以下の箇所。特に複雑な要素はありませんね。

sub generateCurrentNumber {
    my ($base32Secret) = @_;

    # For more details of this magic algorithm, see:
    # http://en.wikipedia.org/wiki/Time-based_One-time_Password_Algorithm

    # need a 16 character hex value
    my $paddedTime = sprintf("%016x", int(time() / $TIME_STEP));
    # this starts with \0's
    my $data = pack('H*', $paddedTime);
    my $key = decodeBase32($base32Secret);

    # encrypt the data with the key and return the SHA1 of it in hex
    my $hmac = hmac_sha1_hex($data, $key);

    # take the 4 least significant bits (1 hex char) from the encrypted string as an offset
    my $offset = hex(substr($hmac, -1));
    # take the 4 bytes (8 hex chars) at the offset (* 2 for hex), and drop the high bit
    my $encrypted = hex(substr($hmac, $offset * 2, 8)) & 0x7fffffff;

    # the token is then the last 6 digits in the number
    my $token = $encrypted % 1000000;
    # make sure it is 0 prefixed
    return sprintf("%06d", $token);
}