【问题标题】:HMAC-SHA-256 in PHPPHP 中的 HMAC-SHA-256
【发布时间】:2016-04-29 15:51:58
【问题描述】:

我必须从这个字符串构建一个授权哈希:

kki98hkl-u5d0-w96i-62dp-xpmr6xlvfnjz:20151110171858:b2c13532-3416-47d9-8592-a541c208f755:hKSeRD98BHngrNa51Q2IgAXtoZ8oYebgY4vQHEYjlmzN9KSbAVTRvQkUPsjOGu4F

此密钥用于 HMAC 哈希函数:

LRH9CAkNs-zoU3hxHbrtY0CUUcmqzibPeN7x6-vwNWQ=

我必须生成的授权哈希是这样的:

P-WgZ8CqV51aI-3TncZj5CpSZh98PjZTYxrvxkmQYmI=

有一些事情需要注意:

  1. 必须使用 RFC 2104 中指定的 HMAC-SHA-256 构建签名。
  2. 签名必须按照RFC 4648 Section 5(安全字母表)中的规定使用与 Base64 URL 兼容的编码。

还有一些生成的伪代码:

Signatur(Request) = new String(encodeBase64URLCompatible(HMAC-SHA-256(getBytes(Z, "UTF-8"), decodeBase64URLCompatible(getBytes(S, "UTF-8")))), "UTF-8")

我在 PHP 中尝试了各种方法,但还没有找到正确的算法。这是我现在的代码:

if(!function_exists('base64url_encode')){
    function base64url_encode($data) {
        $data = str_replace(array('+', '/'), array('-', '_'), base64_encode($data));
        return $data;
    }
}

$str = "kki98hkl-u5d0-w96i-62dp-xpmr6xlvfnjz:20151110171858:b2c13532-3416-47d9-8592-a541c208f755:hKSeRD98BHngrNa51Q2IgAXtoZ8oYebgY4vQHEYjlmzN9KSbAVTRvQkUPsjOGu4F";
$sec = "LRH9CAkNs-zoU3hxHbrtY0CUUcmqzibPeN7x6-vwNWQ=";
$signature = mhash(MHASH_SHA256, $str, $sec);
$signature = base64url_encode($signature);

if($signature != "P-WgZ8CqV51aI-3TncZj5CpSZh98PjZTYxrvxkmQYmI=")
    echo "wrong: $signature";
else
    echo "correct";

它给出了这个签名:

K9lw3V-k5gOedmVwmO5vC7cOn82JSEXsNguozCAOU2c=

如您所见,44 个字符的长度是正确的。请帮我找出错误,这个简单的问题需要我几个小时才能解决。

【问题讨论】:

  • 读了两遍你的问题我还是不知道你的问题/问题是什么。
  • @CharlotteDunois:我需要一个来自字符串的 HMAC 哈希来签名和一个秘密。如果我尝试使用 PHP 生成它,它会失败/给出错误的哈希值。我认为 RFC 规范没有得到满足。
  • 我认为这很大程度上是因为base64url_encode。如果您出于某种原因需要对其进行 urlencoded,请在验证之前在服务器上使用 urlencode 然后 urldecode 它。

标签: php hmac


【解决方案1】:

有几点需要注意:

  1. 您的密钥是 base64 编码的。您必须先对其进行解码,然后才能将其与 php 函数一起使用。这是您错过的最重要的事情。
  2. Mhash 已被 Hash 扩展名淘汰。
  3. 您希望以自定义方式对输出进行编码,因此您需要来自 hmac 函数的原始输出(默认情况下,php 会对它进行十六进制编码)。

所以,使用散列扩展,这就变成了:

$key = "LRH9CAkNs-zoU3hxHbrtY0CUUcmqzibPeN7x6-vwNWQ=";
$str = "kki98hkl-u5d0-w96i-62dp-xpmr6xlvfnjz:20151110171858:b2c13532-3416-47d9-8592-a541c208f755:hKSeRD98BHngrNa51Q2IgAXtoZ8oYebgY4vQHEYjlmzN9KSbAVTRvQkUPsjOGu4F";

function encode($data) {
    return str_replace(['+', '/'], ['-', '_'], base64_encode($data));
}

function decode($data) {
    return base64_decode(str_replace(['-', '_'], ['+', '/'], $data));
}

$binaryKey = decode($key);

var_dump(encode(hash_hmac("sha256", $str, $binaryKey, true)));

输出:

string(44) "P-WgZ8CqV51aI-3TncZj5CpSZh98PjZTYxrvxkmQYmI="

【讨论】:

  • 非常感谢,这正是我需要的结果!问题只是hash_hmac 中的true 和密钥的base64 解码,它也需要base64 URL。
  • 会不会 hash_hmac 总是会生成唯一的字符串...?
  • 不,它的输出是基于输入的字符串和键。给它相同的键和字符串,它会产生相同的输出。
【解决方案2】:

只需使用 PHP 中提供的 hash_hmac() 函数。

例子:

hash_hmac('sha256', $string, $secret);

文档在这里:http://php.net/manual/fr/function.hash-hmac.php

【讨论】:

    猜你喜欢
    • 2012-07-07
    • 2013-01-09
    • 2017-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-08
    • 1970-01-01
    相关资源
    最近更新 更多