我将关键对象的哪一部分传入`openssl_verify`来验证Google签名的JWT?

 维尼饭爱nichkhun_774 发布于 2022-12-31 09:25

我正在尝试使用Google和OpenID Connect实现联合登录系统,并且我无法验证和解析我从Google收到的JWT ID令牌.我在这里关注Google的文档.

根据文档的建议,我正在尝试使用现有的JWT库.GitHub上最流行的PHP版本似乎是PHP_JWT.问题似乎是JWK键的格式.

上面链接的谷歌文档说,从jwks_uri他们的发现文档中显示的端点获取密钥.该端点返回以下内容:

{
 "keys": [
  {
   "kty": "RSA",
   "alg": "RS256",
   "use": "sig",
   "kid": "1771931eb0eb64eb97733e857685be153e079bb9",
   "n": "AMNFQMNJw/EVwrYsyPTnEHWkaPinPb4ngc/SqD701aisFhbU9/wWoKADeFtwfBcWl1qjzIqhPorQElB+2mtiqUh3Qtaazt1x5wA9XnJDe6kjtMGm9nNLMilSVNBilAE8GIdbciMycISfOfL0WRaJrqpNxewNEVZjuYiGzOWahiDP",
   "e": "AQAB"
  },
  {
   "kty": "RSA",
   "alg": "RS256",
   "use": "sig",
   "kid": "7b3bc600209875d3c42ae277a0d018d1d21986ec",
   "n": "AN2UvG5+hNEMIPIbnpPm+JQi6LFWXBPzg3Ltb3xkVmSTjVaCFWppw/ZYRBgpToGKZP9XJstlOE88SDUFSMZIkIqtLpnUqmZax2Zc2gjEB9PhmHSH3/tTmtZ1U0X6V+crqitZ2uc3NV78vCn9/s+WuPwk/gfKBG8Cirb0fgLmsPd9",
   "e": "AQAB"
  }
 ]
}

查看JWT类和方法的源代码,看起来参数可以是一个数组,但是它们希望数组键是和数组值:.它很简单,可以拉出属性并将它们用作数组键,但应该用什么作为数组值?decodeverify$keyskid@param string|resource $key for HS*, a string key works. for RS*, must be a resource of an openssl public keykid

从谷歌的JWKs文档来看,它看起来像我们正在使用RS*,但我不知道关键对象的哪一部分resource of an openssl public key.我已经尝试使用整个stdClass对象而只是n字符串,但两者都失败了openssl_verify.该函数发出通知说:"警告:openssl_verify():提供的密钥参数不能被强制转换为公钥".

所以,显然,我传递的是错误的密钥,但是正确的密钥是什么?

谷歌的库似乎使用不同的端点来获取密钥.该端点似乎返回了一系列证书.我需要使用类似的东西吗?如果是这样,为什么文档会告诉您使用jwks_uri端点?

2 个回答
  • 两个端点包含相同的信息,但格式不同.

    jwks_uri端点给你的模量指数 RSA公钥的价值.您可以使用这两个值来生成你的PEM文件https://www.googleapis.com/oauth2/v1/certs.

    2022-12-31 09:28 回答
  • 对于将来尝试这样做的人,我想提供一个完整的答案;

    JSON密钥中的ne部分jwks_uri给出模数和指数,可用于检索公钥(这是验证签名所需的全部内容).在这篇文章中详细介绍了如何在纯PHP中完成此操作:

    openssl:我如何从模数中获取公钥

    但是,您应该知道Google提供的JSON文档jwks_uri使用URL安全base64编码(即替换了+和/字符的普通base64).如果不考虑这一点,可能仍然会给您一个无效的证书.既然你提到使用php-jwt,使用phpseclib从模数和指数获取公钥的工作代码是:

    $modulus = 'someencodedmodulusvalue';
    $exponent = 'someencodedexponentvalue'; 
    $rsa = new Crypt_RSA();
    
    $modulus = new Math_BigInteger(JWT::urlsafeB64Decode($modulus), 256);
    $exponent = new Math_BigInteger(JWT::urlsafeB64Decode($exponent), 256);
    
    $rsa->loadKey(array('n' => $modulus, 'e' => $exponent));
    $rsa->setPublicKey();
    $pubKey = $rsa->getPublicKey();
    

    2022-12-31 09:29 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有