为啥 openssl_verify() 无法验证我的 JWT 令牌签名?

Posted

技术标签:

【中文标题】为啥 openssl_verify() 无法验证我的 JWT 令牌签名?【英文标题】:Why does openssl_verify() fail to verify my JWT token signature?为什么 openssl_verify() 无法验证我的 JWT 令牌签名? 【发布时间】:2017-05-04 02:09:29 【问题描述】:

代码:

$token = $request->getQueryParams();
$jwt_access_token = $token['access_token'];

$separator = '.';

list($header, $payload, $signature) = explode($separator, $jwt_access_token);

$decoded_signature = base64_decode($signature);

$payload_to_verify = utf8_decode($header . $separator . $payload);

$public_key = file_get_contents($_SERVER['DOCUMENT_ROOT'].'/pubkey.pem');

$verified = openssl_verify($payload_to_verify, $decoded_signature, $public_key, OPENSSL_ALGO_SHA256);

访问令牌示例:

eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpZCI6IjU0YmEzYmQwZDRkYzAxYmZhNmJjYjdjYTIwOTQwY2YzY2NmM2EyNjQiLCJqdGkiOiI1NGJhM2JkMGQ0ZGMwMWJmYTZiY2I3Y2EyMDk0MGNmM2NjZjNhMjY0IiwiaXNzIjoiIiwiYXVkIjoidGVzdGNsaWVudCIsInN1YiI6InNhbGxlIiwiZXhwIjoxNDgyMTIyODY4LCJpYXQiOjE0ODIxMTkyNjgsInRva2VuX3R5cGUiOiJiZWFyZXIiLCJzY29wZSI6bnVsbH0.q-xwz16YbUiaDzdeiNBoaeZIYNx8G6HXLZRMJjpiezotq0nICTokVxuf3OUur6433MhT6wVCUENUeuJfuvLg3wKZWHfXSoTMG77Gkv1Wart6hlIPFqyZ13gyTzquaKRRDoRD9WSBcKXfTF6V59cWHrwAM5nRIQeOzBdYXZPwnV-9RhXUpjUhJ0LKRJsDZ5EwJUFsIDb7oZ70b3uLJqa79h42Dc5mQWj75uIo8mVCmH9N1BPJRn-Hb9ttgpu2oRgDOqsm4zdBz2CfSkPiHa-j6qKEWHocyLQBZ8XLxyvFSAFVIwqv4OVCBHanzbkfY-ZKkKh1THeyiIcrB9ed6vwzRg

公钥:

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs3k2ZkpYqCX94B+qC2yc
4atWx+C5d7kFQAgBrbv5gfFuIST0DLt5lvv0OZZI57+ydNXb2G/jyOJPH3ll2mHS
Z+PKAo9aQoL5iYIjz+yYp2Im51LBh4e0Kt1RSjuy4M5RI1JVSsM9rt3NoLMzehv8
57g+uv1T177cJabDvKeqWdD0qR4N7PE/nV0Hrumz5kP4EnYhN0A2wjbXyyyllxhL
nr3Wqii0XJxBF3AwLUlqP1NYhm2wYq0CTjQrgv3/9WCvr4fSzBitzQAP6ZIFRHO3
F8EIaK6r6cDiP2ABmtTrmPAj3ZpqGVBPnvY9yVrqUS0pMxjvvesJiPd2jGrjLQFN
LQIDAQAB
-----END PUBLIC KEY-----

我无法让openssl_verify() 函数返回 1。它总是返回 0(它无法验证令牌)。我不明白为什么。谁能指出我正确的方向?

【问题讨论】:

您能否详细说明您的问题是什么? ***.com/help/how-to-ask 我无法让 openssl_verify() 函数返回 1。它总是返回 0(它无法验证令牌)。我不明白为什么。 "如果签名正确返回 1,如果签名不正确返回 0,错误返回 -1。"所以,你的签名不正确。 签名根据jwt.io/#debugger有效,所以我认为签名没有错误 【参考方案1】:

失败是因为 JWS 部分不是 Base64 编码的,而是 Base64 Url Safe 编码的。

错误来自线路

$decoded_signature = base64_decode($signature);

应该是

$decoded_signature = base64_decode(strtr($signature, '-_', '+/'));

【讨论】:

以上是关于为啥 openssl_verify() 无法验证我的 JWT 令牌签名?的主要内容,如果未能解决你的问题,请参考以下文章

使用 php-jwt 库解码 firebase 自定义令牌时出现 openssl_verify() 错误

openssl_verify 和“错误:0906D06C:PEM 例程:PEM_read_bio:没有起始行”

openssl_verify():提供的密钥参数不能被强制转换为 .pem 文件的公钥

为啥我无法通过外围设备进行身份验证?

为啥我无法通过 Firebase 的身份验证?

为啥我无法验证 iOS App Archive? [关闭]