PHP JWT验证来自给定令牌的密钥-为什么不';我的两个签名不匹配吗?

PHP JWT验证来自给定令牌的密钥-为什么不';我的两个签名不匹配吗?,php,jwt,token,Php,Jwt,Token,我使用PHP解析从外部API返回的JWT令牌。 解析有效负载非常简单,但我想首先检查令牌中使用的密钥是否与服务器上的密钥匹配。这将作为我的握手。为此,我将使用我认为已使用的密钥重新创建令牌的签名部分(第三部分)。如果结果值匹配,则我知道密钥匹配 例如,我的密钥是:testsecretkey 返回给我的令牌是: 6.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2 ZZZZZZZZZZZZZZZZZZZZZZZZZZZZ

我使用PHP解析从外部API返回的JWT令牌。 解析有效负载非常简单,但我想首先检查令牌中使用的密钥是否与服务器上的密钥匹配。这将作为我的握手。为此,我将使用我认为已使用的密钥重新创建令牌的签名部分(第三部分)。如果结果值匹配,则我知道密钥匹配

例如,我的密钥是:testsecretkey

返回给我的令牌是:

6.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2 ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZihok24jVVi8iE

如果我运行该程序并在“验证签名”框中输入“testscretkey”,然后单击“secretbase64编码”复选框,则所有内容都将签出,并且令牌看起来是正确的

回到我的PHP服务器上,我使用“.”作为分隔符将令牌拆分为3部分($tokenParts)。编码签名(第3部分,上面标记的最后一部分)显示…:

Cqz2mtZ9g_L4BSYTQztzQ4W0VldAf-Ihok24jVVi8iE
我将密钥加密应用于令牌第1部分和第2部分:

$base64UrlSignature = base64_encode(
            hash_hmac(
                'sha256',                               //The correct enc type
                $tokenParts[0] . "." . $tokenParts[1],  //The first 2 parts of the token
                'testsecretkey',                        // The secret key that should have been used
                true
            )
);
…然后我将新签名($base64UrlSignature)与原始编码签名($tokenParts[2])进行比较。如果两者都匹配,则确认握手

但是,即使我使用了相同的键,这些值也不匹配。相反,我的新签名是:

K4Mx71y1yRdQ7xotyR78FzQU8J2xTc65wZbhGFE-s4s
返回到jwt.io(原始令牌信息仍输入框中),如果我取消选中“secret base64 encoded”复选框,我可以看到jwt令牌签名(蓝色)更改为与新签名相同的值($base64UrlSignature)。但这对我来说毫无意义,因为我已经用base64_编码了我的新签名

谁能帮我找出哪里出了错

谢谢“secret base64 encoded”表示您输入的密码是base64编码的。当然,您输入的秘密(“testsecretkey”)并不是真正的base64,但它仍然可以有效地解码

要在PHP中模拟此情况,请执行以下操作:

函数base64\u encode\u url($string){
返回str_replace(['+'、'/'、'=']、['-'、'''''.''、base64_encode($string));
}
函数base64_decode_url($string){
返回base64_解码(str_replace(['-','.'],['+','/'],$string));
}
$signature=base64\u编码\u url(
哈什(
“sha256”,
$tokenParts[0]。“..$tokenParts[1],
base64_解码_url(“testsecretkey”),
真的
)
);
此代码生成
Cqz2mtZ…
,与您在响应中得到的签名相匹配。请注意,您必须使用一个特殊的,保证只生成URL安全字符


您从中获取此响应的API可能希望您为密钥输入base64值,而不是纯文本字符串。

对于HMAC的编码,必须使用Base64url,而不是(默认)base64,请参见例如。否则,Base64编码的结果在字符
+
-
/
\
以及填充(
=
)上有所不同。如果密钥包含字符
\uu
-
(但是
testsecretkey
的情况并非如此),则类似情况也适用于密钥的解码。@Topaco您是对的,我已编辑了我的答案以包含此功能。感谢您的回复。我回到办公室后会试试这个。实际上,我正在使用base64url\u编码和类似的函数引用。我删除了这一部分只是为了简化示例。但我没有考虑过将base64_decodeurl应用于密钥。太棒了,这很管用。再次感谢:)