Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ECKey::convertPublicKeyToPEM() creates invalid public keys #475

Closed
ms2ad opened this issue Aug 23, 2023 · 6 comments · Fixed by #476 or #478
Closed

ECKey::convertPublicKeyToPEM() creates invalid public keys #475

ms2ad opened this issue Aug 23, 2023 · 6 comments · Fixed by #476 or #478
Assignees

Comments

@ms2ad
Copy link

ms2ad commented Aug 23, 2023

Version(s) affected

3.2.7

Description

We have a specific URL, a signature and a set JWKs from Google https://play.google.com/newsstand/api/v3/articleaccess/publicsigningkey/dev to verify the signature.

When trying to verify the signature,

return openssl_verify($input, $der, $pem, $this->getHashAlgorithm()) === 1;
throws the warning

Warning: openssl_verify(): Supplied key param cannot be coerced into a public key

thus verifying the signature always fails.

We compared how web-token/jwt-framework converts the JWK into a public key to how https://8gwifi.org/jwkconvertfunctions.jsp and how https://www.npmjs.com/package/jwk-to-pem does it and while https://8gwifi.org/jwkconvertfunctions.jsp and https://www.npmjs.com/package/jwk-to-pem create the same public key, that openssl ec -inform PEM -pubin -in public.pem -text -noout can properly process, web-token/jwt-framework creates an invalid public key, that openssl fails to read:

read EC key
Could not read public key from public.pem
80E0D9FA01000000:error:1608010C:STORE routines:ossl_store_handle_load_result:unsupported:crypto/store/store_result.c:151:
80E0D9FA01000000:error:1608010C:STORE routines:ossl_store_handle_load_result:unsupported:crypto/store/store_result.c:151:
unable to load Key

The same problem also arises when JWKs from https://play.google.com/newsstand/api/v3/articleaccess/publicsigningkey are converted.

How to reproduce

Execute

$signKeys = json_decode(
    file_get_contents('https://play.google.com/newsstand/api/v3/articleaccess/publicsigningkey/dev'),
    associative: true,
)['keys'];
$jwks = array_map(static fn($key) => new \Jose\Component\Core\JWK($key), $signKeys);

foreach ($jwks as $jwk) {
    echo json_encode($jwk->jsonSerialize()) . "<br><br>";
    echo nl2br(\Jose\Component\Core\Util\ECKey::convertPublicKeyToPEM($jwk)) . "<br><br>";
}

and try verifying the keys with openssl ec -inform PEM -pubin -in public.pem -text -noout, compare keys to https://8gwifi.org/jwkconvertfunctions.jsp.

Possible Solution

No response

Additional Context

Example conversion comparison:

{"kty":"EC","crv":"P-256","x":"GDDdmNtwNvlXN04SEUp20BZJ9im6SQqkP8u4d8G6RAk","y":"AIAxkBwTTqbCcNbqbpk8l_Eh-4KtpgyyHkNJ6K4jnvOv","use":"sig","alg":"ES256","kid":"ayRrlw","key_ops":["verify"]}

web-token/jwt-framework:
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEGDDdmNtwNvlXN04SEUp20BZJ9im6
SQqkP8u4d8G6RAkAgDGQHBNOpsJw1upumTyX8SH7gq2mDLIeQ0noriOe868=
-----END PUBLIC KEY-----

https://8gwifi.org/jwkconvertfunctions.jsp:
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEGDDdmNtwNvlXN04SEUp20BZJ9im6
SQqkP8u4d8G6RAmAMZAcE06mwnDW6m6ZPJfxIfuCraYMsh5DSeiuI57zrw==
-----END PUBLIC KEY-----

node jwk-to-pem:
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEGDDdmNtwNvlXN04SEUp20BZJ9im6
SQqkP8u4d8G6RAmAMZAcE06mwnDW6m6ZPJfxIfuCraYMsh5DSeiuI57zrw==
-----END PUBLIC KEY-----
@Spomky
Copy link
Member

Spomky commented Aug 23, 2023

Hi @ms2ad,

Many thanks for this detailed report.
I investigated and int looks like the JWK is malformed. The y component shall be a string of 32 bytes max, but here it is 33 bytes (AIAxkBwTTqbCcNbqbpk8l_Eh-4KtpgyyHkNJ6K4jnvOv <=> 008031901c134ea6c270d6ea6e993c97f121fb82ada60cb21e4349e8ae239ef3af). There is an extra \0 byte at the beginning of the component.
When this extra byte is removed, the key is correctly converted.

What application/library generated those keys?

@Spomky Spomky self-assigned this Aug 23, 2023
@ms2ad
Copy link
Author

ms2ad commented Aug 23, 2023

Hi @Spomky,

thank you for the quick response. These keys are provided by Google itself, see https://play.google.com/newsstand/api/v3/articleaccess/publicsigningkey/dev and https://play.google.com/newsstand/api/v3/articleaccess/publicsigningkey.

@Spomky Spomky linked a pull request Aug 23, 2023 that will close this issue
@Spomky
Copy link
Member

Spomky commented Aug 23, 2023

I created a PR to solve this problem. But it is worth to warn Google that an extra byte is present in the generated keys.

@ms2ad
Copy link
Author

ms2ad commented Aug 23, 2023

I will check it out locally!

@ms2ad
Copy link
Author

ms2ad commented Aug 23, 2023

@Spomky I can confirm that the fix resolves our issue. Thank you very much!

@Spomky Spomky linked a pull request Aug 23, 2023 that will close this issue
Copy link
Contributor

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 github-actions bot locked as resolved and limited conversation to collaborators Feb 25, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
2 participants