java - php 的 hmac sha256 实现与 java 的不匹配

标签 java php hash sha hmac

我正在尝试在 php 中重现 totp 计算引用官方( https://www.rfc-editor.org/rfc/rfc6238 附录 A)中提到的用 java 编写的测试用例。该引用提供了 sha1、sha256 和 sha512 算法的示例。

我找到了this Rob Swan 的一个很好的例子(参见 8 位数字的例子),它重现了一个很好的测试用例(使用 sha1)。但是,如果我将算法更改为 sha256 或 sha512(并且根据引用输入数据也更改种子),我会得到与引用结果不同的结果。

php 的 hmac 哈希函数可能与 java 的不同吗?

谢谢!

最佳答案

* 解决方案

这是我提到的 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;

这在使用 sha1 算法的假设下工作得很好,该算法返回 20 个字符的字符串。

要抽象该行并使其与任何其他算法兼容,请将此行更改为:

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

现在您已经有了 RFC 6238 totp 计算的通用且可工作的 php 版本!

关于java - php 的 hmac sha256 实现与 java 的不匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17003134/

相关文章:

javascript - Cordova PhoneGap 从 2.2.0 升级到 5.1.1

php - 错误 : Integrity constraint violation: 1052 when Join in Laravel Eloquent

java - 如何从java中的字符串中提取最长的子字符串(具有不同的连续字符)

java - Hibernate:子集合的级联删除

java - 在 Eclipse 中更新 ADT 导致许多错误

ruby - 在 ruby​​ 2.2.0 中创建哈希的新方法

java - 检索线性/二次散列的探针长度

php - PHP 7.4 中的循环引用

PHP MySQL内容保存到按id排序的数组

c# - PDF 签名 - 嵌入单独签名的哈希