There's a certain kind of frustration that only developers know. When you need to do something relatively simple, but the tooling forces you through 4 manual steps, terminal commands you have to Google every time, and output files you're not sure are formatted correctly.
That's exactly what happened to me with JWK keys.
The Problem
I was integrating with a service that required keys in JWK (JSON Web Key) format. Not PEM. JWK.
I already knew how to generate a key pair with OpenSSL:
openssl ecparam -name prime256v1 -genkey -noout -out private.pem
openssl ec -in private.pem -pubout -out public.pem
But converting those PEM files to JWK? That's where it got annoying. I ended up writing a one-off Node.js script, manually constructing the JWK object, double-checking that the kty, crv, x, y, d fields were all correct, and saving the output.
It worked. But I thought: I'm probably going to need to do this again. And I don't want to redo this every time.
So I built jwk-cli-tool.
What It Does
It's an interactive CLI that handles the full workflow:
- Generate a new PEM key pair (EC or RSA)
- Convert PEM files to JWK JSON format
- Or do both in one flow
You get four files at the end: *.private.pem, *.public.pem, *.private.jwk.json, and *.public.jwk.json.
Supported algorithms:
- EC: ES256, ES384, ES512
- RSA: RS256, RS384, RS512
How to Use It
No installation needed. Just run:
npx jwk-cli-tool
You'll get an interactive menu:
? What would you like to do?
> Generate new PEM key pair
Generate JWK JSON files
Exit
From there it walks you through naming the key, picking the algorithm, and choosing whether to generate fresh PEM files or use existing ones from your /keys folder.
The generated files land in keys/ for PEM files and outputs/ for JWK JSON files. Both folders are created automatically if they don't exist. If a key name already exists, it asks before overwriting.
A Quick Look at the Output
Running through the flow for an ES256 key produces something like this for the public JWK:
{
"kty": "EC",
"use": "sig",
"alg": "ES256",
"kid": "myapp",
"crv": "P-256",
"x": "f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU",
"y": "x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0"
}
The private JWK includes the d parameter on top of that.
Tech Stack
Built with Node.js and TypeScript, using @inquirer/prompts for the TUI and Node's built-in crypto module. No heavy external crypto dependencies.
The outputs write to process.cwd(), so wherever you run npx jwk-cli-tool from, that's where your keys/ and outputs/ folders appear.
Source Code
The project is open source:
PRs and feedback welcome. If there are algorithms or features you'd find useful (EdDSA/Ed25519, JWKS array output, non-interactive flag mode for CI pipelines) feel free to open an issue.
Sometimes the best tools come from solving your own problem. Hopefully this saves someone else the same 30 minutes of OpenSSL googling.
Top comments (0)