What does the JWK & JWKS to PEM Public Key Converter do?
The JWK & JWKS to PEM Public Key Converter transforms cryptographic JSON Web Keys (kty: "RSA", kty: "EC", kty: "OKP") and multi-key JWKS JSON sets into standard X.509 SubjectPublicKeyInfo (SPKI) -----BEGIN PUBLIC KEY----- PEM certificates. It parses Identity Provider JWKS endpoints from Auth0, AWS Cognito, Google OIDC, Firebase, Okta, and Keycloak, allowing developers to verify JWT signatures in legacy microservices, reverse proxies (NGINX/Caddy), Go, Python, and Java backends without requiring live OIDC discovery requests.
Core Concepts
Understanding JSON Web Key structures and PEM representations:
- JWK Modulus & Exponent: RSA public keys in JWK format are represented via Base64URL-encoded strings:
n(modulus) ande(public exponent, typicallyAQABor65537). Converting to PEM builds the standard ASN.1 DER sequence. - Elliptic Curve Coordinates: EC keys (e.g.
crv: "P-256") define uncompressed curve coordinatesxandy. The converter encodes these into the standard SPKI format expected by OpenSSL. - Key ID (
kid) Routing: JWKS endpoints publish multiple rotating keys. Matching thekidheader parameter of an incoming JWT token ensures the correct public key is used for signature validation.
How to use the tool?
- Paste JWK or JWKS JSON: Paste a single JWK object or the full JSON response from
https://<auth-domain>/.well-known/jwks.jsoninto the editor. - Select Key ID (
kid): For multi-key sets, choose the specific key matching your token'skidfrom the dropdown selector. - Copy or Download: Click Convert to PEM Public Key to copy the certificate or download
public_key.pem.
Related Developer Utilities
If you work with JSON Web Tokens, OAuth 2.0, and cryptographic certificates, explore these complementary tools:
- JWT Expiry & TTL Checker: Inspect JWT timestamps, clock skew, and calculate remaining time-to-live.
- Base64URL to Base64 Converter: Convert URL-safe Base64 strings to standard RFC 4648 Base64.
- SSH Public Key Format Converter: Convert OpenSSH keys into RFC 4716 and PEM formats.
- AWS IAM Policy Visualizer: Visualize and validate AWS IAM JSON policies.
REST API Integration
Blueutils provides a free REST API endpoint (POST https://blueutils.com/api/jwt/jwk-to-pem) to programmatically convert JWK and JWKS sets into PEM public key certificates.
API Request Parameters
| Name | Type | Description | Example |
|---|---|---|---|
rawText |
String | JSON string of a single JWK or JWKS {"keys": [...]} set. |
"{ \"kty\": \"RSA\", \"e\": \"AQAB\", \"n\": \"...\" }" |
options.kid |
String | Optional Key ID to select from a multi-key JWKS set. | "auth0-2026-key1" |
API Request Payload Examples
cURL
curl -X POST https://blueutils.com/api/jwt/jwk-to-pem \
-H "Content-Type: application/json" \
-d '{
"rawText": "{\"kty\":\"RSA\",\"e\":\"AQAB\",\"n\":\"u1W1to1bXx7_TupaoAYEDBuW3HBAfCEddFsJq6BxbHK0nU7d357M6xWUKKA054ndMQgEKqVCKzZXbq2UdVgTk7EI8t1xEE9zaQ_Z9yY-y0L0VpU4-x0k8R4N7I3l32P4V4x_g_xP9Q_mR9w-4wQ\"}"
}'Python
import requests
url = "https://blueutils.com/api/jwt/jwk-to-pem"
payload = {
"rawText": '{"kty":"RSA","e":"AQAB","n":"u1W1to1bXx7_TupaoAYEDBuW3HBAfCEddFsJq6BxbHK0nU7d357M6xWUKKA054ndMQgEKqVCKzZXbq2UdVgTk7EI8t1xEE9zaQ_Z9yY-y0L0VpU4-x0k8R4N7I3l32P4V4x_g_xP9Q_mR9w-4wQ"}'
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.json())Java
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class Main {
public static void main(String[] args) throws Exception {
String jsonPayload = """
{
"rawText": "{\\"kty\\":\\"RSA\\",\\"e\\":\\"AQAB\\",\\"n\\":\\"u1W1to1bXx7_TupaoAYEDBuW3HBAfCEddFsJq6BxbHK0nU7d357M6xWUKKA054ndMQgEKqVCKzZXbq2UdVgTk7EI8t1xEE9zaQ_Z9yY-y0L0VpU4-x0k8R4N7I3l32P4V4x_g_xP9Q_mR9w-4wQ\\"}"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://blueutils.com/api/jwt/jwk-to-pem"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(jsonPayload))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}API Response Parameters
| Name | Type | Description | Example |
|---|---|---|---|
isValid |
Boolean | Indicates whether conversion succeeded. | true |
isJwks |
Boolean | Whether input was a multi-key set. | false |
totalKeys |
Number | Count of valid keys extracted. | 1 |
pem |
String | Output PEM public key certificate string. | "-----BEGIN PUBLIC KEY-----\n..." |
selectedKey.kty |
String | Cryptographic key type (e.g. RSA, EC). | "RSA" |
selectedKey.kid |
String | Key ID identifier string. | "auth0-2026-key1" |
API Response Payload Examples
Success Response (HTTP 200 OK)
{
"isValid": true,
"isJwks": false,
"totalKeys": 1,
"selectedKey": {
"kid": "default",
"kty": "RSA",
"alg": "RS256",
"pem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA..."
},
"pem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA..."
}Validation Failure Response (HTTP 400 Bad Request)
{
"isValid": false,
"error": "Invalid JSON format. Please paste a valid JWK object or JWKS JSON set."
}Rate Limit Exceeded Response (HTTP 429 Too Many Requests)
{
"error": "API rate limit exceeded. Please wait or contact support@blueutils.com."
}Why use an API to convert JWK to PEM?
Integrating the JWK to PEM Converter API into server boot scripts, CI/CD pipelines, or AI agent tool calling provides key benefits:
- Offline JWT Signature Verification: Allows microservices to verify JWT tokens without querying the IdP's JWKS endpoint on every cold start.
- Optimized Token Efficiency for AI Agents: LLMs frequently fail to calculate valid ASN.1 DER byte sequences when generating PEM keys. Calling the API formats standard SPKI certificates deterministically.
- Universal Cryptographic Compatibility: Provides standard PEM files for systems (like OpenSSL, NGINX
auth_jwt, or legacy Go services) that lack built-in JWKS JSON parsers.
Native Usage
How to inspect and convert JWK to PEM natively:
Linux / Unix (Bash with OpenSSL & Node.js)
# Convert JWK via native Node.js one-liner
node -e '
const crypto = require("crypto");
const jwk = { kty: "RSA", e: "AQAB", n: "..." };
console.log(crypto.createPublicKey({ key: jwk, format: "jwk" }).export({ type: "spki", format: "pem" }));
' > public_key.pem
# Inspect generated PEM public key with OpenSSL
openssl pkey -pubin -in public_key.pem -text -nooutWindows (PowerShell)
# Convert JWK to PEM in PowerShell using Node.js crypto engine
$jwkJson = '{"kty":"RSA","e":"AQAB","n":"..."}'
node -e "const crypto = require('crypto'); console.log(crypto.createPublicKey({ key: JSON.parse(process.argv[1]), format: 'jwk' }).export({ type: 'spki', format: 'pem' }))" $jwkJson | Out-File -Encoding ascii public_key.pem
# Verify with OpenSSL on Windows
openssl pkey -pubin -in public_key.pem -text -nooutWindows (Command Prompt)
:: Inspect public key certificate with OpenSSL
openssl pkey -pubin -in public_key.pem -text -nooutPython
Using cryptography:
import json
import base64
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization
def jwk_to_pem(jwk_dict):
n_bytes = base64.urlsafe_b64decode(jwk_dict['n'] + '==')
e_bytes = base64.urlsafe_b64decode(jwk_dict['e'] + '==')
n = int.from_bytes(n_bytes, byteorder='big')
e = int.from_bytes(e_bytes, byteorder='big')
public_numbers = rsa.RSAPublicNumbers(e, n)
pubkey = public_numbers.public_key()
return pubkey.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
).decode('utf-8')Java
Using Java RSAPublicKeySpec:
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.spec.RSAPublicKeySpec;
import java.util.Base64;
public class JwkConverter {
public static PublicKey getPublicKey(String b64urlN, String b64urlE) throws Exception {
byte[] nBytes = Base64.getUrlDecoder().decode(b64urlN);
byte[] eBytes = Base64.getUrlDecoder().decode(b64urlE);
BigInteger n = new BigInteger(1, nBytes);
BigInteger e = new BigInteger(1, eBytes);
RSAPublicKeySpec spec = new RSAPublicKeySpec(n, e);
return KeyFactory.getInstance("RSA").generatePublic(spec);
}
}