I am working in a restricted environment and don't have the ability to utilise any third party systems that would make this simple, such as Firebase/php-jwt
I have received a JWT I would like to verify. I have a JWK from which I need to reconstruct the public key, to complete the verification.
The JWK is as follows
{
"kty": "RSA",
"use": "enc",
"n": "ozmvkuGzWNHs9cEcC5PWwbG-dmSjPcoQFxEbqH_fBjkj_nfTTKshdiSq5ciulWEa_rrqQ2qwcSADNxtTzRR1qfud-NvsM8VltT7xDuVVqPTZoWLKa0BWXgQQ-1mCm1KdGltYWccB0R1LoF-rb3DEEZySsHvqErYzYt4M_rqjEiK5Y9y1h3k1h5Yk4zGLWchko3jiDS-pVevvWsQsN-Y3KuB19485G9P_MXLtfJWQ4wC4jlo9etdD_hgDfxX-hQy3wuwHfHifLdxvxiB8X5Is4m6DuY4_7hS5RwXAjO1QSd-zUYZNT_2yWVR56_jyiZEiOdgIm9QtLPZCTKzqsXoqZQ",
"e": "AQAB"
}
The code I am using to generate the public key is as follows
$jwk = json_decode($jwk);
$rsaPublicKey = "-----BEGIN PUBLIC KEY-----\n";
$rsaPublicKey .= "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA{$jwk->modulus}";
$rsaPublicKey .= "{$jwk->exponent}\n-----END PUBLIC KEY-----";
$isSignatureValid = openssl_verify($dataToVerify, $signature, $rsaPublicKey, OPENSSL_ALGO_SHA256);
This results in an error
openssl_verify(): supplied key param cannot be coerced into a public key
I feel like I'm missing something obvious and I am somehow generating the key incorrectly. I tried asking ChatGPT for help but it gave me many different solutions, all of which led back to the same error. Further reading has led me to some ideas similar to the AI suggestions, but again all led to the same error
These included:
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
to the modulus, this seems to be something to do with RSA keys, but I don't really understand what this isI'm really not sure what else I can do here, this feels like it should be such a simple thing, but I'm just not getting it and I've run out of angles to approach
I thought it might just be a simple formatting issue some simple code could fix, so I wrote the following to try to produce a valid pem. The code runs with your JWT and the example pem shown without emitting the '...cannot be coerced into a public key' error. That doesn't mean it is correct. Anyway, you can play with this. It might be useful, or not.
<?php
$json = array();
$json['kty'] = 'RSA';
$json['use'] = 'enc';
$json['n'] = 'ozmvkuGzWNHs9cEcC5PWwbG-dmSjPcoQFxEbqH_fBjkj_nfTTKshdiSq5ciulWEa_rrqQ2qwcSADNxtTzRR1qfud-NvsM8VltT7xDuVVqPTZoWLKa0BWXgQQ-1mCm1KdGltYWccB0R1LoF-rb3DEEZySsHvqErYzYt4M_rqjEiK5Y9y1h3k1h5Yk4zGLWchko3jiDS-pVevvWsQsN-Y3KuB19485G9P_MXLtfJWQ4wC4jlo9etdD_hgDfxX-hQy3wuwHfHifLdxvxiB8X5Is4m6DuY4_7hS5RwXAjO1QSd-zUYZNT_2yWVR56_jyiZEiOdgIm9QtLPZCTKzqsXoqZQ';
$json['e'] = 'AQAB';
$rsaPublicHeader = "-----BEGIN PUBLIC KEY-----\n";
$rsaPublicBody = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA".strtr($json['n'].'ID'.$json['e'], '-_', '+/');
$rsaPublicFooter = "-----END PUBLIC KEY-----";
$pem = $rsaPublicHeader;
$rsaPublicBodyLen = strlen($rsaPublicBody);
for ($i = 0; $i<$rsaPublicBodyLen; $i+=64) {
$pem .= substr($rsaPublicBody, $i, 64)."\n";
}
$pem .= $rsaPublicFooter;
$dataToVerify = "";
$signature = "";
/*
// Example pem taken from https://github.com/Strobotti/php-jwk
$pem = "-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4dGQ7bQK8LgILOdLsYzf
ZjkEAoQeVC/aqyc8GC6RX7dq/KvRAQAWPvkam8VQv4GK5T4ogklEKEvj5ISBamdD
Nq1n52TpxQwI2EqxSk7I9fKPKhRt4F8+2yETlYvye+2s6NeWJim0KBtOVrk0gWvE
Dgd6WOqJl/yt5WBISvILNyVg1qAAM8JeX6dRPosahRVDjA52G2X+Tip84wqwyRpU
lq2ybzcLh3zyhCitBOebiRWDQfG26EH9lTlJhll+p/Dg8vAXxJLIJ4SNLcqgFeZe
4OfHLgdzMvxXZJnPp/VgmkcpUdRotazKZumj6dBPcXI/XID4Z4Z3OM1KrZPJNdUh
xwIDAQAB
-----END PUBLIC KEY-----";
*/
echo $pem."\n";
$isSignatureValid = openssl_verify($dataToVerify, $signature, $pem, OPENSSL_ALGO_SHA256);
if ($isSignatureValid) {
echo ("Valid\n");
} else {
echo ("Invalid\n");
}
?>
Output
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAozmvkuGzWNHs9cEcC5PW
wbG+dmSjPcoQFxEbqH/fBjkj/nfTTKshdiSq5ciulWEa/rrqQ2qwcSADNxtTzRR1
qfud+NvsM8VltT7xDuVVqPTZoWLKa0BWXgQQ+1mCm1KdGltYWccB0R1LoF+rb3DE
EZySsHvqErYzYt4M/rqjEiK5Y9y1h3k1h5Yk4zGLWchko3jiDS+pVevvWsQsN+Y3
KuB19485G9P/MXLtfJWQ4wC4jlo9etdD/hgDfxX+hQy3wuwHfHifLdxvxiB8X5Is
4m6DuY4/7hS5RwXAjO1QSd+zUYZNT/2yWVR56/jyiZEiOdgIm9QtLPZCTKzqsXoq
ZQIDAQAB
-----END PUBLIC KEY-----
Invalid