0

totp 計算リファレンス ( https://www.rfc-editor.org/rfc/rfc6238付録 A)の公式に記載されている Java で記述されたテスト ケースを php で再現しようとしています。このリファレンスは、sha1、sha256、および sha512 アルゴリズムの例を提供します。

Rob Swan (8 桁の例を参照) によるこの素敵な例を見つけました。これは、1 つのテスト ケース (sha1 を使用) をうまく再現しています。しかし、アルゴリズムをsha256またはsha512に変更すると(参照入力データに従ってシードも変更すると)、参照のものとは異なる結果が得られました。

php の hmac ハッシュ関数は java のものと違うのでしょうか?

ありがとうございました!

4

1 に答える 1

1

* 解決

これは、私が言及した Rob Swan による php 実装のコピーです。

<?php

// Define your secret seed
// NB: this is a hexadecimal representation of the example
// ASCII string which is: 12345678901234567890
$secret_seed = "3132333435363738393031323334353637383930";

// Determine the time window as 30 seconds
$time_window = 30;

// Set the timestamp manually
$exact_time = 1111111109;

// Round the time down to the time window
$rounded_time = floor($exact_time/$time_window);

// Pack the counter into binary
$packed_time = pack("N", $rounded_time);

// Make sure the packed time is 8 characters long
$padded_packed_time = str_pad($packed_time,8, chr(0), STR_PAD_LEFT);

// Pack the secret seed into a binary string
$packed_secret_seed = pack("H*", $secret_seed);

// Generate the hash using the SHA1 algorithm
$hash = hash_hmac ('sha1', $padded_packed_time, $packed_secret_seed, true);

// NB: Note we have change the exponent in the pow function 
// from 6 to 8 to generate an 8 digit OTP not a 6 digit one 

// Extract the 8 digit number fromt the hash as per RFC 6238
$offset = ord($hash[19]) & 0xf;
$otp = (
    ((ord($hash[$offset+0]) & 0x7f) << 24 ) |
    ((ord($hash[$offset+1]) & 0xff) << 16 ) |
    ((ord($hash[$offset+2]) & 0xff) << 8 ) |
    (ord($hash[$offset+3]) & 0xff)
) % pow(10, 8);

// NB: Note that we are padding to 8 characters not 6 for this example

// Add any missing zeros to the left of the numerical output
$otp = str_pad($otp, 8, "0", STR_PAD_LEFT);

// Display the output, which should be 
echo "This should display 07081804: " . $otp;

?>

キーポイントは次の行です。

$offset = ord($hash[19]) & 0xf;

これは、20 文字の文字列を返す sha1 アルゴリズムを使用するという仮説の下でうまく機能します。

行を抽象化し、他のアルゴリズムと互換性を持たせるには、この行を次のように変更します。

$offset = ord($hash[strlen($hash)-1]) & 0xf;

これで、RFC 6238 totp 計算の一般的で機能する php バージョンができました。

于 2013-06-09T14:16:29.527 に答える