ワンタイムパスワード(OTP)の生成
はじめに
D言語でワンタイムパスワードの生成処理を実装してみました。
ワンタイムパスワード(OTP)の種類
ワンタイムパスワードには、生成回数をベースにしたHOTP
と生成時刻をベースにしたTOTP
の2種類があります。
それぞれ、RFCで定義されています。
HOTP : An HMAC-Based One-Time Password Algorithm
RFC4226
TOTP : Time-Based One-Time Password Algorithm
RFC6238
関連用語
HOTP
やTOTP
を生成するためにHMAC
、SHA-1
を利用します。
HMAC : Hash-based Message Authentication Code
RFC 2104
SHA-1 : Secure Hash Algorithm - 1
RFC 3174
これらは、D言語の標準ライブラリを使って実装できます。
D言語での HMAC-SHA-1
ソースコード
ワンタイムパスワードの生成処理の実装例です。
いつものごとく、入力パラメータargs
のチェックは省略しています。
/+ dub.sdl:
name "otp"
dependency "base32" version="~>0.1.0"
+/
// dub build --build=release --single otp.d
import std.conv;
import std.datetime;
import std.digest.hmac;
import std.digest.sha : SHA1;
import std.stdio;
import base32;
int getOTP(string key, ulong input)
{// one time password
ubyte[] data = new ubyte[8];
for ( int i = 0; i < 8; i++ ){
data[7 - i] = input & 0xff;
input >>= 8;
}
auto hmac = HMAC!SHA1(Base32.decode(key));
hmac.put(data);
ubyte[20] digest = hmac.finish();
int offset = digest[19] & 0x0f;
int number = (digest[offset ] & 0x7f) << 24 |
(digest[offset + 1] & 0xff) << 16 |
(digest[offset + 2] & 0xff) << 8 |
(digest[offset + 3] & 0xff);
return ( number % 1_000_000 );
}
void main(string[] args)
{
int number;
if ( args.length < 3 ){
// TOTP
ulong input = Clock.currTime.toUnixTime() / 30;
number = getOTP(args[1], input);
} else {
// HOTP
number = getOTP(args[1], args[2].to!ulong);
}
writefln("%06d", number);
}
コンパイル
コマンドプロンプト
D:\Dev> dub build --build=release --single otp.d
Performing "release" build using D:\Dev\dmd2\windows\bin\dmd.exe for x86_64.
base32 0.1.0: target for configuration "library" is up to date.
otp ~master: building configuration "application"...
Linking...
To force a rebuild of up-to-date targets, run again with --force.
試してみる
D:\Dev> dub build --build=release --single otp.d
Performing "release" build using D:\Dev\dmd2\windows\bin\dmd.exe for x86_64.
base32 0.1.0: target for configuration "library" is up to date.
otp ~master: building configuration "application"...
Linking...
To force a rebuild of up-to-date targets, run again with --force.
WinAuthを使って、実行結果を比較検証しました。
WinAuth
のSecret Key
は、Base32でエンコードされています。
D言語のbase32パッケージを使えば、エンコードやデコードすることができます。
Base32の実装例
/+ dub.sdl:
name "base32sample"
dependency "base32" version="~>0.1.0"
+/
// dub build --build=release --single base32sample.d
import std.stdio;
import std.string;
import base32;
void main(string[] args)
{
writeln(Base32.encode("12345678901234567890"));
writeln(cast(string)Base32.decode("GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ"));
}
D:\Dev> dub build --build=release --single base32sample.d
Performing "release" build using D:\Dev\dmd2\windows\bin\dmd.exe for x86_64.
base32 0.1.0: target for configuration "library" is up to date.
base32sample ~master: building configuration "application"...
Linking...
To force a rebuild of up-to-date targets, run again with --force.
D:\Dev> base32sample
GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ
12345678901234567890
HOTPの生成
Secret Key
と生成回数をパラメータとして渡すとHOTP
を生成します。
生成回数が増えるごとに、異なるパスワードが生成されます。
D:\Dev> otp GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ 1
287082
D:\Dev> otp GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ 2
359152
TOTPの生成
Secret Key
のみをパラメータとして渡すとTOTP
を生成します。
パスワードは、30秒ごとに新たに生成されます。
D:\Dev> otp GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ
088383
D:\Dev> otp GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ
428063
参考情報
Author And Source
この問題について(ワンタイムパスワード(OTP)の生成), 我々は、より多くの情報をここで見つけました https://qiita.com/devmynote/items/aed5a96a206c9e472864著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .