jwt-framework icon indicating copy to clipboard operation
jwt-framework copied to clipboard

RSA keys cannot be used to verify PS signature

Open samuelwei opened this issue 6 months ago • 2 comments

Version(s) affected

4.x

Description

Using the JWSVerifier one can check if a Signed Token has been correctly signed. For OpenID Connect I provide a keyset with all keys the IDP annouces to encrypt keys with. Auth0 signs keys using PS256 with the RSA keys.

This libaray fails the correctly validate the PS256 signature with an RSA key.

Reason for this is the strict checking inside KeyChecker::checkKeyAlgorithm

From my understanding, it should accept RSA keys for PS signatures

How to reproduce

The last line should result true, however the current implementation returns false

use Jose\Component\Core\AlgorithmManagerFactory;
use Jose\Component\Core\JWK;
use Jose\Component\Core\JWKSet;
use Jose\Component\KeyManagement\JWKFactory;
use Jose\Component\Signature\Algorithm\PS256;
use Jose\Component\Signature\Algorithm\RS256;
use Jose\Component\Signature\Serializer\CompactSerializer;
use Jose\Component\Signature\Serializer\JWSSerializerManager;
use Jose\Component\Signature\JWSVerifier;
use Jose\Component\Core\JWKSet;

$algorithmManagerFactory = new AlgorithmManagerFactory();
$algorithmManagerFactory->add("RS256", new RS256());
$algorithmManagerFactory->add("PS256", new PS256());

$token =
  "eyJhbGciOiJQUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.iOeNU4dAFFeBwNj6qdhdvm-IvDQrTa6R22lQVJVuWJxorJfeQww5Nwsra0PjaOYhAMj9jNMO5YLmud8U7iQ5gJK2zYyepeSuXhfSi8yjFZfRiSkelqSkU19I-Ja8aQBDbqXf2SAWA8mHF8VS3F08rgEaLCyv98fLLH4vSvsJGf6ueZSLKDVXz24rZRXGWtYYk_OYYTVgR1cg0BLCsuCvqZvHleImJKiWmtS0-CymMO4MMjCy_FIl6I56NqLE9C87tUVpo1mT-kbg5cHDD8I7MjCW5Iii5dethB4Vid3mZ6emKjVYgXrtkOQ-JyGMh6fnQxEFN1ft33GX2eRHluK9eg";

$serializerManager = new JWSSerializerManager([new CompactSerializer()]);
$jws = $serializerManager->unserialize($token);

$signature = $jws->getSignature(0);
$alg = $signature->getProtectedHeaderParameter("alg");
$algorithmManager = $algorithmManagerFactory->create([$alg]);
$jwsVerifier = new JWSVerifier($algorithmManager);

$jwk = JWKFactory::createFromValues([
  "kty" => "RSA",
  "alg" => "RS256",
  "n" =>
    "u1SU1LfVLPHCozMxH2Mo4lgOEePzNm0tRgeLezV6ffAt0gunVTLw7onLRnrq0_IzW7yWR7QkrmBL7jTKEn5u-qKhbwKfBstIs-bMY2Zkp18gnTxKLxoS2tFczGkPLPgizskuemMghRniWaoLcyehkd3qqGElvW_VDL5AaWTg0nLVkjRo9z-40RQzuVaE8AkAFmxZzow3x-VJYKdjykkJ0iT9wCS0DRTXu269V264Vf_3jvredZiKRkgwlL9xNAwxXFg0x_XFw005UWVRIkdgcKWTjpBP2dPwVZ4WWC-9aGVd-Gyn1o0CLelf4rEjGoXbAAEgAqeGUxrcIlbjXfbcmw",
  "e" => "AQAB",
  "use" => "sig"
]);

$jwkSet = new JWKSet([$jwk]);

$jwsVerifier->verifyWithKeySet($jws, $jwkSet, 0);

Possible Solution

https://github.com/web-token/jwt-framework/blob/4.1.x/src/Library/Core/Util/KeyChecker.php#L38

if ($alg !== $algorithm) {

+            // Allow RSA keys to be used for PS
+           $alternativeAlgName = str_replace('PS', 'RS', $algorithm);

+            if($alg !== $alternativeAlgName) {
                throw new InvalidArgumentException(sprintf('Key is only allowed for algorithm "%s".', $alg));
+            }
}

Additional Context

No response

samuelwei avatar Jun 17 '25 11:06 samuelwei

Hi @SamuelWei, thank you for the detailed report.

This behavior is intentional and compliant with RFC 7517 section 4.4, which defines the alg parameter as indicating the intended algorithm for the key. When this parameter is present, it is interpreted as a usage constraint (same for use or other parameters). Therefore, a JWK with alg": RS256 must not be used to verify or sign tokens using a different algorithm, such as PS256 even if both algorithms use RSA keys.

This strictness prevents algorithm substitution attacks and aligns with security recommendations, including those from RFC 8725, section 3.3.

You should contact the issuer of the token/keyset

If you really want to use it, you may alter the JWK to remove or change the alg parameter but this is not a compliant or recommended solution as it opens the door to algorithm confusion attacks (e.g. using RSA keys across RS* and PS* with different paddings).

Spomky avatar Jun 17 '25 12:06 Spomky

Thank's for your quick reply and this detailed answer. I observed this issue while using Auth0

samuelwei avatar Jun 17 '25 12:06 samuelwei

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

github-actions[bot] avatar Aug 03 '25 05:08 github-actions[bot]