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 值而不是明文字符串。
我正在使用 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 值而不是明文字符串。