HOTP Algorithm that works according to the RCF http://tools.ietf.org/html/draft-mraihi-oath-hmac-otp-04
The test cases from the RCF document the ASCII string as "123456787901234567890".
But the hex decoded to a string is "12345678901234567890".
Secret="12345678901234567890";
Count:
0 755224
1 287082
<?php
function oath_hotp($key,$counter) {
// Convert to padded binary string
$data = pack ('C*', $counter);
$data = str_pad($data,8,chr(0),STR_PAD_LEFT);
// HMAC
return hash_hmac('sha1',$data,$key);
}
function oath_truncate($hash, $length = 6) {
// Convert to dec
foreach(str_split($hash,2) as $hex) {
$hmac_result[]=hexdec($hex);
}
// Find offset
$offset = $hmac_result[19] & 0xf;
// Algorithm from RFC
return (
(($hmac_result[$offset+0] & 0x7f) << 24 ) |
(($hmac_result[$offset+1] & 0xff) << 16 ) |
(($hmac_result[$offset+2] & 0xff) << 8 ) |
($hmac_result[$offset+3] & 0xff)
) % pow(10,$length);
}
print "<pre>";
print "Compare results with:"
print " http://tools.ietf.org/html/draft-mraihi-oath-hmac-otp-04\n";
print "Count\tHash\t\t\t\t\t\tPin\n";
for($i=0;$i<10;$i++)
print $i."\t".($a=oath_hotp("12345678901234567890",$i))
print "\t".oath_truncate($a)."\n";
hash_hmac
(PHP 5 >= 5.1.2, PECL hash >= 1.1)
hash_hmac — HMAC 方式を使用してハッシュ値を生成する
説明
string hash_hmac
( string $algo
, string $data
, string $key
[, bool $raw_output= false
] )
パラメータ
- algo
-
選択したアルゴリズムの名前 (すなわち "md5"、"sha256"、"haval160,4" など…)。
- data
-
ハッシュするメッセージ。
- key
-
HMAC 方式でのメッセージダイジェストを生成するために使用する 共有の秘密鍵。
- raw_output
-
TRUE を設定すると、生のバイナリデータを出力します。 デフォルト (FALSE) の場合は小文字の 16 進数値となります。
返り値
raw_output が true に設定されていない場合は、 メッセージダイジェストの計算結果を小文字の 16 進数値形式の文字列で 返します。もし true に設定されていた場合は、メッセージダイジェストが そのままのバイナリ形式で返されます。
例
例1 hash_hmac() の例
<?php
echo hash_hmac('ripemd160', 'The quick brown fox jumped over the lazy dog.', 'secret');
?>
上の例の出力は以下となります。
b8e7ae12510bdfb1812e463a7f086122cf37e4f7
参考
- hash() - ハッシュ値 (メッセージダイジェスト) を生成する
- hash_init() - 段階的なハッシュコンテキストを初期化する
- hash_hmac_file() - HMAC 方式を使用して、指定されたファイルの内容からハッシュ値を生成する
hash_hmac
torben dot egmose at gmail dot com
22-Mar-2009 07:40
22-Mar-2009 07:40
Carlos Averett(caverett*@*corecodec,net)
03-Jul-2008 10:54
03-Jul-2008 10:54
Generating OATH-compliant OTP (one time passwords) results in PHP:
<?php
$otp = oath_truncate (oath_hotp ($key, $counter), $length);
function oath_hotp ($key, $counter) {
// Counter
$bin_counter = pack ('C*', $counter);
// Pad to 8 chars
if (strlen ($bin_counter) < 8) {
$bin_counter = str_repeat (chr(0), 8 - strlen ($bin_counter)) . $bin_counter;
}
// HMAC
$hash = hash_hmac ('sha1', $bin_counter, $key);
return $hash;
}
function oath_truncate ($hash, $length = 6) {
// The last byte is used as an offset
$offset = hexdec (substr ($hash, 38)) & 0xf;
// Extract the relevant part, and clear the first bit
$hex_truncated = substr ($hash, $offset * 2, 8);
$bin_truncated = decbin (hexdec ($hex_truncated));
$bin_truncated[0] = '0';
$dec_truncated = bindec ($bin_truncated);
return substr ($dec_truncated, 0 - $length);
}
?>