A minimalist illustration of a stylized browser window with a geometric, glowing key emerging from it on a neutral background.

Deriving an RSA Public Key from a Private Key Using the Web Crypto API

While tools such as OpenSSL or Node.js provide methods to derive the public key from the private key:

The Web Crypto API does not include a direct method to derive an RSA public key from a private key.

However, you can achieve this by exporting the private key in JSON Web Key (JWK) format, extracting the modulus (n) and public exponent (e), and re-importing them as a public key:

See RFC 8017 (PKCS #1 v2.2) - RSA Public Key for more information on the RSA public key format.

/**
 * Derive the public key from a private key in PEM format using the Web Crypto API.
 * @param {string} privateKeyPem - The private key in PEM format.
 * @return {Promise<CryptoKey>} - The public key as a CryptoKey.
 * @see https://developer.mozilla.org/de/docs/Web/API/CryptoKey
 */
async function publicKeyFromPrivateKey(privateKeyPem) {
  const base64 = pemToBase64(privateKeyPem); // remove PEM headers, remove newlines
  const keyData = base64ToUint8Array(base64);

  // Import the private key
  // RSASSA-PKCS1-v1_5 refers to the RSA signature algorithm defined in rfc8017 https://www.rfc-editor.org/rfc/rfc8017#section-8.2
  const rsaParams = { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" };
  const privateKey = await crypto.subtle.importKey("pkcs8", keyData, rsaParams, true, ["sign"]);

  // Export the private key in JWK format
  const privateKeyJwk = await crypto.subtle.exportKey("jwk", privateKey);
  // Extract the modulus and public exponent from the private JWK
  const { n, e } = privateKeyJwk;
  // Create a new JWK with the public components
  const publicKeyJwk = { kty: "RSA", e, n };

  // Re-import the public key from our generated public JWK object
  return crypto.subtle.importKey("jwk", publicKeyJwk, rsaParams, true, ["verify"]);
}
  1. Convert the PEM to Base64 and then to a Uint8Array.
  2. Import the private key using importKey.
  3. Export the key in JWK format, revealing the public components.
  4. Create a new JWK with n and e, then import it as a public key.

You can find the full example on GitHub: https://gist.github.com/PutziSan/99a1aaede16c3f223fd59ae6d47a0d5e

Interactive Example

Below is an interactive example to derive the public key from a private key using the Web Crypto API directly in the browser (no server-side processing required, your private key stays private):

Generated Public Key in PEM format: