ecdsa.com

Export public key PEM · WebCrypto

How to export a public key as PEM in WebCrypto

WebCrypto exports a public key as binary SPKI, and PEM is just that DER base64-wrapped between header lines — so exporting a public key PEM from the browser is exportKey plus a five-line formatter. The key must have been created extractable.

Tested against the WebCrypto API in Node.js 26 — the same crypto.subtle interface browsers implement.

Same recipe in:Node.jsPythonGoOpenSSLWebCrypto
export the public key as SPKI PEM
const spki = await crypto.subtle.exportKey("spki", publicKey);
 
const b64 = btoa(String.fromCharCode(...new Uint8Array(spki)));
const pem = `-----BEGIN PUBLIC KEY-----\n${
b64.match(/.{1,64}/g).join("\n")
}\n-----END PUBLIC KEY-----\n`;
console.log(pem);
public key from a private CryptoKey (via JWK)
// exportKey("spki", privateKey) throws — SPKI is public-only.
// Route through JWK and drop the private scalar d:
const jwk = await crypto.subtle.exportKey("jwk", privateKey);
delete jwk.d;
jwk.key_ops = ["verify"];
const publicKey = await crypto.subtle.importKey(
"jwk", jwk,
{ name: "ECDSA", namedCurve: "P-256" },
true, ["verify"],
);

How it works

  1. exportKey("spki", …) works only on public keys and only if the key was created with extractable: true.
  2. PEM formatting is mechanical: base64 the DER, wrap at 64 columns, add the PUBLIC KEY header and footer, end with a newline.
  3. To publish the public half of a private CryptoKey, export as JWK, delete d, re-import as a public key, then export SPKI (second snippet).

Gotchas

  • String.fromCharCode(...bytes) blows the argument limit on huge buffers; EC SPKI is ~91 bytes so it is safe here, but reuse this pattern for certificates and it will bite — chunk instead.
  • A non-extractable key cannot be exported at all — exportKey rejects with InvalidAccessError. Extractability is decided at generateKey/importKey time and cannot be flipped later.
  • When deriving public from private via JWK, forgetting to delete d re-imports a *private* key — and anything you then publish is the private key in JWK clothing. Delete d, always.

Related recipes