mrkeyoor.com_
Sat 08 Aug 21:57 UTC
npmSecurityupdated 08 Aug 2026

node-rsa

node-rsa is a high-level RSA key, encryption, and signature library for Node.js 20+ and modern browser bundles. It generates keys, imports and exports PKCS#1, PKCS#8, OpenSSH, DER, PEM, and raw components, encrypts with OAEP or legacy PKCS#1 v1.5 padding, and signs with PSS or PKCS#1 v1.5. Version 2 is a TypeScript rewrite with Node crypto fast paths, a separate pure-JavaScript browser build, built-in types, and hardened padding and key validation. It is an RSA toolbox, not a complete envelope format, certificate stack, JWT implementation, or key-management service.

Verdict

node-rsa 2.0 is a credible convenience layer when RSA interoperability and format conversion are the actual requirements. For new application protocols, prefer a defined format such as JOSE and keep encryption hybrid, settings explicit, and private keys out of browser code.

API stability3/5The familiar constructor, import, export, encrypt, decrypt, sign, and verify methods survived the TypeScript rewrite, but version 2 made consequential changes: Node 20 is required, CommonJS needs .default, browser returns Uint8Array, bundled types replace @types, and the default signature scheme changed from PKCS#1 v1.5 to PSS.
Docs5/5The README documents every scheme, encoding, key format, environment distinction, return type, and the PKCS#1 v1.5 oracle warning. A detailed migration guide explains ten upgrade steps, and the changelog records performance work plus specific security fixes, protocol references, test counts, and browser-bundle behavior.
Maintenance5/5Version 2.0.0 was published in May 2026, the repository was pushed in August 2026, and it is not archived. The recent rewrite added native Node crypto paths, browser conditional exports, strict TypeScript, extensive tests, key-validation checks, blinding, and constant-time padding work, which is unusually substantive maintenance for an older package name.
Ecosystem4/5node-rsa records 3,572,711 weekly downloads and 1,380 GitHub stars, accepts common PKCS#1, PKCS#8, OpenSSH, PEM, DER, and component forms, and supports both modern Node and browsers. Its ecosystem score stops short of five because raw RSA APIs integrate less safely than standards-centered JOSE, Web Crypto, or PKI libraries.

Use it if

  • You must interoperate with an existing RSA key or protocol and want one API for key formats, encryption, decryption, signing, and verification
  • You need the same RSA operations in Node.js and a modern browser bundle without Buffer or crypto polyfills
  • You are migrating node-rsa 1.x code and can review the version 2 signing-default and module-shape changes
  • You need to convert among PEM, DER, OpenSSH, and raw RSA components as part of application code
Skip it if

Setup reality

Install with npm install node-rsa. There are no native builds, credentials, peer dependencies, or config files, but version 2 requires Node.js 20 and its migration is not a blind package bump. ESM uses import NodeRSA from 'node-rsa'; CommonJS uses require('node-rsa').default. Remove @types/node-rsa because version 2 includes its own declarations and the old DefinitelyTyped package exposes the wrong namespace shape. Browser builds depend on a bundler that honors conditional exports and get ESM plus Uint8Array results; Node gets ESM or CommonJS and Buffer-compatible results. Old browser Buffer, crypto, and process shims should be removed. Make padding choices explicit at the call site: use OAEP with SHA-256 for new encryption unless an external protocol requires something else, and use PSS with SHA-256 for new signatures. The library's OAEP default is SHA-1, while the version 2 signing default changed from PKCS#1 v1.5 to PSS, so implicit settings create interoperability surprises. RSA has a scheme-dependent plaintext limit exposed by getMaxMessageSize(); for files or large payloads, encrypt data with an authenticated symmetric cipher and use RSA only to wrap its key. Key generation is synchronous, so do not put it on a latency-sensitive request path. Store private PEM outside source control, restrict filesystem or secret-manager access, never send it to the browser, and define key IDs and rotation outside this package because node-rsa does not manage either.

Patterns

Generate a 2048-bit RSA key pairgenerate-key-pair

import NodeRSA from 'node-rsa';

const key = new NodeRSA({ b: 2048 });
console.log(key.getKeySize());

Version 2 refuses keys below 512 bits and warns below 2048; key generation is synchronous, so keep it off hot request paths.

Export private and public PEMexport-pem-keys

const privatePem = key.exportKey('pkcs8-private-pem');
const publicPem = key.exportKey('pkcs8-public-pem');

Store privatePem in a secret manager or permission-restricted file; only the public key is safe to distribute.

Import a PEM key with automatic detectionimport-pem-key

import NodeRSA from 'node-rsa';

const key = new NodeRSA(process.env.RSA_PRIVATE_KEY);
if (!key.isPrivate()) throw new Error('private RSA key required');

PEM input can omit the format, but raw DER must include an exact format such as pkcs8-private-der.

Encrypt with explicit OAEP and SHA-256encrypt-oaep-sha256

const publicKey = new NodeRSA(publicPem);
publicKey.setOptions({
  encryptionScheme: { scheme: 'pkcs1_oaep', hash: 'sha256' },
});

const ciphertext = publicKey.encrypt('small secret', 'base64');

OAEP is the default scheme but its default hash is SHA-1, so set SHA-256 explicitly and match it during decryption.

Decrypt matching OAEP ciphertextdecrypt-oaep-sha256

const privateKey = new NodeRSA(privatePem);
privateKey.setOptions({
  encryptionScheme: { scheme: 'pkcs1_oaep', hash: 'sha256' },
});

const plaintext = privateKey.decrypt(ciphertext, 'utf8');

The private key must use the same OAEP hash and label as the encrypting side or decryption fails.

Reject plaintext that exceeds one RSA blockcheck-message-limit

const bytes = new TextEncoder().encode(message);
const max = publicKey.getMaxMessageSize();
if (bytes.byteLength > max) {
  throw new Error(`use hybrid encryption; RSA limit is ${max} bytes`);
}
const encrypted = publicKey.encrypt(bytes, 'base64');

The limit changes with modulus size and padding; use RSA to wrap a symmetric key instead of splitting a large payload into RSA blocks.

Sign with explicit RSA-PSS and SHA-256sign-pss-sha256

const signer = new NodeRSA(privatePem);
signer.setOptions({
  signingScheme: { scheme: 'pss', hash: 'sha256', saltLength: 32 },
});

const signature = signer.sign(payload, 'base64');

PSS is version 2's default, but spelling out the scheme, hash, and salt length avoids cross-version and cross-language ambiguity.

Verify a signature with the public keyverify-pss-signature

const verifier = new NodeRSA(publicPem);
verifier.setOptions({
  signingScheme: { scheme: 'pss', hash: 'sha256', saltLength: 32 },
});

const valid = verifier.verify(payload, signature, 'utf8', 'base64');

verify returns false for an invalid signature; the payload encoding and all PSS parameters must match the signer.

Load version 2 from CommonJSuse-commonjs

const NodeRSA = require('node-rsa').default;

const key = new NodeRSA(publicPem);

Version 2 uses the standard ESM-to-CommonJS default export shape; require('node-rsa') by itself returns a module object.

Encrypt in a modern browser bundleuse-browser-bundle

import NodeRSA from 'node-rsa';

const publicKey = new NodeRSA(publicPem);
publicKey.setOptions({
  encryptionScheme: { scheme: 'pkcs1_oaep', hash: 'sha256' },
});
const ciphertext = publicKey.encrypt(formValue, 'base64');

Use a bundler with conditional-exports support. Do not put a private key in browser code, and remove old Buffer or crypto polyfills.

Convert PKCS#1 private PEM to PKCS#8convert-key-format

const key = new NodeRSA(pkcs1Pem, 'pkcs1-private-pem');
const pkcs8Pem = key.exportKey('pkcs8-private-pem');

Converting representation does not encrypt the private key or add password protection; secure storage remains your responsibility.

Export an OpenSSH public keyexport-openssh-public

const key = new NodeRSA(privateOrPublicPem);
const authorizedKey = key.exportKey('openssh-public');

The OpenSSH public format is suitable for authorized_keys-style interchange; it is not an X.509 certificate.

Alternatives

PackageRegistryPick it when
josenpmChoose it for JWS, JWT, JWE, JWK, and standards-defined algorithm and serialization behavior
node-forgenpmChoose it when RSA is only one part of a browser-capable PKI task involving certificates, CSRs, ASN.1, or TLS structures
openpgpnpmChoose it for OpenPGP messages, identities, armored keys, and multi-recipient encryption rather than raw RSA operations
@noble/curvesnpmChoose it for audited modern elliptic-curve primitives when no RSA interoperability requirement exists