Q&A
What is node crypto.createPublicKey(key)?
Overview
Node's crypto module supports asymmetric cryptography, which uses key pairs: a private key (kept secret) and a public key (shared freely). crypto.createPublicKey() turns raw key material into a structured KeyObject that Node's crypto functions can use. It's part of the modern KeyObject-based API (Node 11+) that replaced passing raw PEM strings around.
graph TD
A[Input: PEM/DER public key,<br/>or a private key, or JWK] --> B["crypto.createPublicKey(key)"]
B --> C[KeyObject type='public']
C --> D[verify signatures]
C --> E[public-key encryption]
C --> F[export as PEM/DER/JWK]
style B fill:#1e1b4b,color:#fff
Signature
const { createPublicKey } = require("crypto");
const keyObject = createPublicKey(key);
key can be:
- A PEM string or Buffer containing a public key.
- An object specifying
{ key, format: 'pem'|'der', type: 'spki'|'pkcs1' }. - A private key (string, Buffer, or KeyObject) - Node derives the corresponding public key.
- A JWK (JSON Web Key) via
{ key: jwk, format: 'jwk' }.
Example: from a PEM public key
const { createPublicKey } = require("crypto");
const pem = `-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...
-----END PUBLIC KEY-----`;
const publicKey = createPublicKey(pem);
console.log(publicKey.type); // 'public'
console.log(publicKey.asymmetricKeyType); // e.g. 'rsa', 'ec', 'ed25519'
Example: derive public key from a private key
A handy feature - you can produce the public key from the private one:
const { generateKeyPairSync, createPublicKey } = require("crypto");
const { privateKey } = generateKeyPairSync("rsa", { modulusLength: 2048 });
const publicKey = createPublicKey(privateKey); // derived from the private key
Using the KeyObject: verifying a signature
The most common use of a public key is verifying a signature created with the matching private key:
const { createSign, createVerify, generateKeyPairSync, createPublicKey } = require("crypto");
const { privateKey } = generateKeyPairSync("rsa", { modulusLength: 2048 });
const publicKey = createPublicKey(privateKey);
const data = "important message";
const signature = createSign("sha256").update(data).end().sign(privateKey);
const isValid = createVerify("sha256").update(data).end().verify(publicKey, signature);
console.log(isValid); // true
Exporting a KeyObject
const pem = publicKey.export({ type: "spki", format: "pem" });
const jwk = publicKey.export({ format: "jwk" }); // JSON Web Key
KeyObject vs Raw Strings
Older Node code passed PEM strings directly to crypto functions. The KeyObject API (returned by createPublicKey/createPrivateKey/createSecretKey) is preferred because it:
- Validates and parses the key once.
- Carries metadata (
type,asymmetricKeyType). - Avoids repeatedly re-parsing PEM on every operation.
- Supports clean export to multiple formats.
Common Use Cases
- JWT verification - verify tokens signed with RS256/ES256 using the issuer's public key.
- Digital signatures - verify that data came from the holder of the private key.
- Public-key encryption - encrypt data only the private-key holder can decrypt (with
publicEncrypt). - Key exchange / TLS internals.
Why This Matters in Interviews
Node/security interviews use this to check understanding of asymmetric cryptography (key pairs), the difference between public and private keys, and the modern KeyObject API. Knowing that you can derive the public key from a private key, and that public keys are for verifying signatures and encrypting (private keys sign and decrypt), is the core conceptual content.
Common Pitfalls
- Confusing which key does what (public = verify/encrypt; private = sign/decrypt).
- Passing a wrongly-formatted PEM/DER and getting parse errors (check
type/format). - Exposing or logging private keys (only the public key is safe to share).
- Mixing up
spki(SubjectPublicKeyInfo) vspkcs1key encodings.
References
- Node.js crypto
createPublicKey: https://nodejs.org/api/crypto.html#cryptocreatepublickeykey - Node.js KeyObject class: https://nodejs.org/api/crypto.html#class-keyobject