【问题标题】:Verify JWT signature with RSA public key in PHP在 PHP 中使用 RSA 公钥验证 JWT 签名
【发布时间】:2025-12-04 05:50:01
【问题描述】:

在 PHP 中,我正在尝试使用 AWS 的 RSA 公钥(我从 https://cognito-identity.amazonaws.com/.well-known/jwks_uri 处的模数/指数生成)验证 AWS 身份验证令牌(从 getOpenIdTokenForDeveloperIdentity 返回的 JWT)。关键以适当的页眉/页脚-----BEGIN RSA PUBLIC KEY----- 等开头。我查看了一些PHP 库,例如Emarref\Jwt\Jwt,但是我得到了错误:error:0906D06C:PEM routines:PEM_read_bio:no start line。这一切都归结为基本的 php 函数:openssl_verify

我已经查看了 openssl-verify 的 php.net/manual,但我仍然不清楚参数详细信息。需要的算法是RS512

我能够毫无问题地使用 node.js 验证 JWT 令牌(相同的密钥和令牌)。为此,我使用了库:https://github.com/auth0/node-jsonwebtoken

不知道为什么这在 PHP 中不起作用。我可以不使用 RSA 公钥吗?

function verifyKey($public_key) {
  $jwt = new Emarref\Jwt\Jwt();

  $algorithm = new Emarref\Jwt\Algorithm\Rs512();
  $factory = new Emarref\Jwt\Encryption\Factory();
  $encryption = $factory->create($algorithm);
  $encryption->setPublicKey($public_key);
  $context = new Emarref\Jwt\Verification\Context($encryption);
  $token = $jwt->deserialize($authToken);

  try {
    $jwt->verify($token, $context);
  } catch (Emarref\Jwt\Exception\VerificationException $e) {
    debug($e->getMessage());
  }
}

【问题讨论】:

    标签: php amazon-web-services rsa jwt php-openssl


    【解决方案1】:

    我能够让这个库正常工作。但是我必须使用 KeyFactory::createFromValues 而不是 KeyFactory::createFromPEM 来构建密钥。谢谢!

    【讨论】:

    • 这应该是对答案的评论,而不是另一个答案。如果答案有效,您应该将其标记为正确 asnwer
    【解决方案2】:

    您可以尝试使用另一个 PHP 库吗:https://github.com/Spomky-Labs/jose

    // File test.php
    require_once __DIR__.'/vendor/autoload.php';
    
    use Jose\Checker\ExpirationChecker;
    use Jose\Checker\IssuedAtChecker;
    use Jose\Checker\NotBeforeChecker;
    use Jose\Factory\KeyFactory;
    use Jose\Factory\LoaderFactory;
    use Jose\Factory\VerifierFactory;
    use Jose\Object\JWKSet;
    use Jose\Object\JWSInterface;
    
    // We create a JWT loader.
    $loader = LoaderFactory::createLoader();
    
    // We load the input
    $jwt = $loader->load($input);
    
    if (!$jws instanceof JWSInterface) {
        die('Not a JWS');
    }
    
    // Please note that at this moment the signature and the claims are not verified
    
    // To verify a JWS, we need a JWKSet that contains public keys (from RSA key in your case).
    // We create our key object (JWK) using a RSA public key
    $jwk = KeyFactory::createFromPEM('-----BEGIN RSA PUBLIC KEY-----...');
    
    // Then we set this key in a keyset (JWKSet object)
    // Be careful, the JWKSet object is immutable. When you add a key, you get a new JWKSet object.
    $jwkset = new JWKSet();
    $jwkset = $jwkset->addKey($jwk);
    
    
    // We create our verifier object with a list of authorized signature algorithms (only 'RS512' in this example)
    // We add some checkers. These checkers will verify claims or headers.
    $verifier = VerifierFactory::createVerifier(
        ['RS512'],
        [
            new IssuedAtChecker(),
            new NotBeforeChecker(),
            new ExpirationChecker(),
        ]
    );
    
    $is_valid = $verifier->verify($jws, $jwkset);
    
    // The variable $is_valid contains a boolean that indicates the signature is valid or not.
    // If a claim is not verified (e.g. the JWT expired), an exception is thrown.
    
    //Now you can use the $jws object to retreive all claims or header key/value pairs
    

    【讨论】: