import { readFileSync, writeFileSync } from "node:fs";import { createPublicKey } from "node:crypto"; // PEM -> JWK: any public key type; the curve and key type come from the PEMconst jwk = createPublicKey(readFileSync("pub.pem")).export({ format: "jwk" });writeFileSync("out.jwk.json", JSON.stringify(jwk));console.log(JSON.stringify(jwk)); console.log(JSON.stringify(createPublicKey(readFileSync("ed25519.pem")).export({ format: "jwk" })));import { readFileSync, writeFileSync } from "node:fs";import { createPublicKey } from "node:crypto"; // JWK -> PEM: a public JWK becomes an SPKI "BEGIN PUBLIC KEY" blockconst jwk = JSON.parse(readFileSync("pub.jwk.json", "utf8"));const pem = createPublicKey({ key: jwk, format: "jwk" }).export({ type: "spki", format: "pem" });writeFileSync("out.pem", pem);process.stdout.write(pem);How it works
createPublicKey(pem)readsBEGIN PUBLIC KEY(and also certificates, from which it takes the key).export({ format: "jwk" })returns a plain object:kty,crv,x,yfor EC;kty,crv,xfor Ed25519;kty,n,efor RSA.createPublicKey({ key: jwk, format: "jwk" })reads the JWK and validates it — an EC point that is not on the curve throws.export({ type: "spki", format: "pem" })writes the standard PEM with 64-character lines and a final newline, so the round trip reproduces the original file exactly.
Gotchas
- Exporting a private KeyObject as JWK includes
d, the private key. CallcreatePublicKey(privateKey)first when the JWK is meant for publishing. createPublicKeyalso accepts a private JWK and quietly returns its public half, so code that should only ever see public keys does not notice private material being passed in.- An invalid point fails with
ERR_CRYPTO_INVALID_JWK: Invalid JWK EC key, the same message as a missing member — checkxandyagainst the issuer's published values. - The JWK has no
kid,useoralg: add them before publishing it in a JWKS (kidis often the RFC 7638 thumbprint).
Related recipes
- How to export a public key as PEM in Node.js
- How to compute a JWK thumbprint (RFC 7638) in Node.js
- How to verify a JWT with a JWKS in Node.js
- How to convert a PEM public key to a JWK and back in WebCrypto
- How to convert a PEM public key to a JWK and back in Python
- How to convert a PEM public key to a JWK and back in Go