PHP JWT 从给定令牌验证密钥 - 为什么我的 2 个签名不匹配?

PHP JWT validating a secret key from a given token - why don't my 2 signatures match?

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

举个例子,我的Secret Key是:testsecretkey

返回给我的Token是:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6IjIzMTc2MiIsIklkIjoiMTM0IiwiSWRQZXJzb24iOiIxMTkiLCJQZXJzb25lblJvbGxlbiI6Ilt7XCJSb2xsZVwiOjEsXCJJZFwiOjE0MTg5fSx7XCJSb2xsZVwiOjIsXCJJZFwiOjExOX0se1wiUm9sbGVcIjozLFwiSWRcIjoxMDY5MH1dIiwibmJmIjoxNjEwNDYxNjA2LCJleHAiOjE2MTA0NjUyMDYsImlhdCI6MTYxMDQ2MTYwNn0.Cqz2mtZ9g_L4BSYTQztzQ4W0VldAf-Ihok24jVVi8iE

如果我 运行 通过 https://jwt.io/ 并在“验证签名”框中输入“testscretkey”并单击“secret base64 编码”复选框,一切都会检查出来,令牌看起来是正确的.

回到我在 PHP 的服务器上,我使用“.”将令牌分成 3 个部分($tokenParts)。作为分隔符。编码签名(第 3 部分,上面令牌的最后一部分)显示...:[=​​15=]

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(原始令牌信息仍输入框中)如果我取消勾选“秘密 base64 编码”复选框,我可以看到 JWT 令牌签名(蓝色)更改为与我的新签名相同的值($base64UrlSignature)。但这对我来说毫无意义,因为我有 base64_encoded 我的新签名。

谁能帮我找出我哪里出错了?

谢谢

“秘密 base64 编码”意味着您输入的秘密是 base64 编码的。当然,您输入的秘密(“testsecretkey”)不是真正的 base64,但它仍然有效解码。

要在 PHP 中进行模拟:

function base64_encode_url($string) {
    return str_replace(['+','/','='], ['-','_',''], base64_encode($string));
}

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

$signature = base64_encode_url(
    hash_hmac(
            "sha256",
            $tokenParts[0] . "." . $tokenParts[1],
            base64_decode_url("testsecretkey"),
            true
        )
);

此代码生成 Cqz2mtZ...,与您在响应中获得的签名相匹配。请注意,您必须使用特殊的 modified version of base64 保证只生成 URL 安全字符。

您收到此回复的 API 可能希望您输入密钥的 base64 值而不是明文字符串。