How to generate RSA public key using exponent (e) and modulus (n) to verify the signature of a json web token?

2.9k Views Asked by At

My goal is to verify my id_token in JSON Web Token (JWT) format using jsonwebtoken verify method, which requires a public key as the second argument. My web application is a node js application.

According to Ping ID's documentation, I am supposed to generate the RSA public key using the exponent(e) and modulus(n). Here is an example that is applicable for my id_token:

   {
    "kty": "RSA",
    "kid": "IlOPtWXUcpiPttmr-K7DmehzeRM",
    "use": "enc",
    "n": "qv2XCvfUfW0bG547B1xieE0-GN8xLuCdzGcIWsYMP-fn1vR2ptR7XOp_kW-etlxSDT2MVyzdXbG9eQCgeBk-Ajgbyn4AaFScJt9ibGyE-5hUvkSJRTP-jlJjlPniYsKcjEY3C-QzyRcEIHoOHOEuevIFwVvKNRgEVYyx3CmkmIXcfw35R1tORNjCec_NA6dawx_LPpS0endjNz2m_iijLquKenrsKSKVnBprfVtBh_myuNQD5CfhBnzZRmAUfr0PoVMDBb0r_rWaV1Q64zQWSeCql7CSWq4U8RNhogd0eCZOOv45plIUwoxkdNg0Rzkp-OEtKRLaHonJ_OZ_sxa8-w",
    "e": "AQAB"
    },

The question is, how do I generate the public key using these values? Is there a node js library that does this?

I am new to cryptography, so pardon my beginner's question.

2

There are 2 best solutions below

0
On

If you want to use jsonwebtoken's verify method, then you can do it by converting your jwk into a pem string, for example, using jwt-to-pem. Using the example on the package's website, it goes like this:

First you install

npm i jwt-to-pem -D

And then you convert and use

import * as jwtToPem from 'jwt-to-pem';
import {verify} from 'jsonwebtoken';

let jwk = {
    "kty": "RSA",
    "kid": "IlOPtWXUcpiPttmr-K7DmehzeRM",
    "use": "enc",
    "n": "qv2XCvfUfW0bG547B1...",
    "e": "AQAB"
};

let pem_str = jwtToPem(jwk);

//Finally, verification for some token
verify(id_token, pem_str);

And that's all. I saw in node's crypto documentation that you should be able to do it without external dependencies, but I didn't manage it!

1
On

You can use node's Crypto module to easily convert a jwk to a public key(pem), without using external dependencies.

import crypto from 'crypto';

let publicKey = crypto.createPublicKey({
  key: {
    "kty": "RSA",
    "kid": "IlOPtWXUcpiPttmr-K7DmehzeRM",
    "n": "qv2XCvfUfW0bG547B1xieE0-GN8xLuCdzGcIWsYMP-fn1vR2ptR7XOp_kW-etlxSDT2MVyzdXbG9eQCgeBk-Ajgbyn4AaFScJt9ibGyE-5hUvkSJRTP-jlJjlPniYsKcjEY3C-QzyRcEIHoOHOEuevIFwVvKNRgEVYyx3CmkmIXcfw35R1tORNjCec_NA6dawx_LPpS0endjNz2m_iijLquKenrsKSKVnBprfVtBh_myuNQD5CfhBnzZRmAUfr0PoVMDBb0r_rWaV1Q64zQWSeCql7CSWq4U8RNhogd0eCZOOv45plIUwoxkdNg0Rzkp-OEtKRLaHonJ_OZ_sxa8-w",
    "e": "AQAB"
  }, format: 'jwk'
});

You can then use this to verify the jwt.

let pem = publicKey.export({ type: 'pkcs1', format: 'pem' });
jwt.verify(jwtToken, pem, (err, decoded) => {
})