empty
empty

Reputation: 11

PHP : verify JWS with JWK (x5c)

Context: I want to implement payment with Payconiq. When the payment is done, Payconiq calls my API to give me payment information (status, etc).

I'm using Symfony and web-token/jwt-bundle to verify JWS.

1/ I use 'base64_decode' to get the header from the token (token format is like: header.payload.signature with an empty payload)

2/ I get the json JWKs from URL: the JWK that always seems to be used is like:

{
      "kty": "EC",
      "use": "sig",
      "x5t#S256": "******************",
      "crv": "P-256",
      "kid": "kid.2021",
      "alg": "ES256",
      "x5c": [],
      "x": *******,
      "y": *******

3/ I want to verify the signature with this JWK. I do :

$serializerManager = new JWSSerializerManager([new CompactSerializer(),]);

$jws = $serializerManager->unserialize($token);

$isVerified = $jwsVerifier->verifyWithKey($jws, $jwk, 0, $payload);

(public function verifyWithKey(JWS $jws, JWK $jwk, int $signature, ?string $detachedPayload = null): bool)

My payload: body request sent by Payconiq (payment information).

$isVerified is always false.

I don't know if the problem comes from my payload or the way I use the library (documentation shows an example with a JWK like

{
    "kty": "oct",
    "k": "dzI6nbW4OcNF-AtfxGAmuyz7IpHRudBI0WgGjZWgaRJt6prBn3DARXgUR8NVwKhfL43QBIU2Un3AvCGCHRgY4TbEqhOi8-i98xxmCggNjde4oaW6wkJ2NgM3Ss9SOX9zS3lcVzdCMdum-RwVJ301kbin4UtGztuzJBeg5oVN00MGxjC2xWwyI0tgXVs-zJs5WlafCuGfX1HrVkIf5bvpE0MQCSjdJpSeVao6-RSTYDajZf7T88a2eVjeW31mMAg-jzAWfUrii61T_bYPJFOXW8kkRWoa1InLRdG6bKB9wQs9-VdXZP60Q4Yuj_WZ-lO7qV9AEFrUkkjpaDgZT86w2g'
}

There's is a "k" key and the result is ok (isVerified = true).

But with a JWK without "k" and with "x5c", isVerified still false.

Could someone please help me?

Upvotes: 0

Views: 1609

Answers (1)

Spomky-Labs
Spomky-Labs

Reputation: 16695

It looks like the verification failed because you have have forgotten to set the appropriate signature algorithm (ES256) in the $jwsVerifier object.

Find hereafter a valid example. Please change the JWK and token values with you data.

use Jose\Component\Core\AlgorithmManager;
use Jose\Component\Core\JWK;
use Jose\Component\Signature\Algorithm\ES256;
use Jose\Component\Signature\Serializer\CompactSerializer;
use Jose\Component\Signature\JWSVerifier;

$jwk = JWK::createFromJson('{"kty":"EC","crv":"P-256","x":"f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU","y":"x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0"}');
$token = 'eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8ISlSApmWQxfKTUJqPP3-Kg6NU1Q';

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

$algorithmManager = new AlgorithmManager([new ES256()]);
$jwsVerifier = new JWSVerifier($algorithmManager);

$isVerified = $jwsVerifier->verifyWithKey($jws, $jwk, 0);
if ($isVerified)  {
    var_dump('Signature is valid');
} else {
    var_dump('Signature is NOT valid!');
}

In case the payload is detached from the token, you can set it as fourth parameter of the verifyWithKey method. Note that it shall not be base 64 encoded.

<?php

use Jose\Component\Core\AlgorithmManager;
use Jose\Component\Core\JWK;
use Jose\Component\Signature\Algorithm\ES256;
use Jose\Component\Signature\Serializer\CompactSerializer;
use Jose\Component\Signature\JWSVerifier;

$jwk = JWK::createFromJson('{"kty":"EC","crv":"P-256","x":"f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU","y":"x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0"}');
$token = 'eyJhbGciOiJFUzI1NiJ9..DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8ISlSApmWQxfKTUJqPP3-Kg6NU1Q';
$payload = base64_decode('eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ');

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

$algorithmManager = new AlgorithmManager([new ES256()]);
$jwsVerifier = new JWSVerifier($algorithmManager);

$isVerified = $jwsVerifier->verifyWithKey($jws, $jwk, 0, $payload);
if ($isVerified)  {
    var_dump('Signature is valid');
} else {
    var_dump('Signature is NOT valid!');
}

Upvotes: 1

Related Questions