Synchronous Node.js PGP API backed by Rust rPGP.
npm install node-rpgpnode-rpgp is stable for the documented synchronous RSA and ECC PGP subset.
Unsupported PGP features fail with stable UNSUPPORTED_FEATURE errors instead of being silently accepted.
| Feature | Status |
|---|---|
| RSA key generation | Supported for 2048, 3072, and 4096-bit keys |
| ECC default profile | Supported: Ed25519 primary key plus X25519 encryption subkey |
curve: "curve25519" |
Supported as the Ed25519/X25519 encryption-capable profile |
curve: "ed25519" |
Supported as the Ed25519/X25519 encryption-capable profile |
| NIST ECC curves | Unsupported, throws UNSUPPORTED_FEATURE |
| Passphrase-protected private key generation | Supported for RSA and ECC |
| Armored public key parsing | Supported through rPGP |
| Armored private key parsing | Supported through rPGP |
| Multiple armored private key parsing | Supported by parsing each complete armor block through rPGP |
| Armored message parsing | Supported through rPGP |
| Public-key encryption | Supported for one RSA or ECC recipient |
| Private-key decryption | Supported for one RSA or ECC private key |
| Text roundtrip | Supported |
| Binary plaintext roundtrip | Supported through armored encrypted messages |
| Binary encrypted output | Unsupported, throws UNSUPPORTED_FEATURE |
These features currently throw UNSUPPORTED_FEATURE:
- NIST ECC curves:
nistP256,nistP384,nistP521 - signing
- signature verification
- password-only message encryption/decryption
- multiple encryption recipients
- multiple decryption keys
- binary encrypted output
- binary message parsing with
readMessage({ binaryMessage })
const {
createMessage,
readMessage,
readKey,
readPrivateKey,
readPrivateKeys,
decryptKey,
encrypt,
decrypt,
generateKey,
} = require("node-rpgp");The public API is synchronous and does not expose Sync-suffixed function names.
const { generateKey, readKey, readPrivateKey } = require("node-rpgp");
const generated = generateKey({
type: "rsa",
rsaBits: 2048,
userIDs: [{ name: "Example User", email: "user@example.com" }],
});
const publicKey = readKey({ armoredKey: generated.publicKey });
const privateKey = readPrivateKey({ armoredKey: generated.privateKey });Generate the default ECC profile:
const generated = generateKey({
type: "ecc",
curve: "curve25519",
userIDs: [{ name: "Example User", email: "user@example.com" }],
});curve: "ed25519" currently selects the same Ed25519/X25519 profile. Ed25519 is used for the primary signing/certification key; X25519 is used for the encryption subkey.
const { generateKey, readPrivateKey, decryptKey } = require("node-rpgp");
const generated = generateKey({ type: "ecc", passphrase: "change me" });
const locked = readPrivateKey({ armoredKey: generated.privateKey });
const unlocked = decryptKey({ privateKey: locked, passphrase: "change me" });unlocked.decrypted is true.
Passphrase-protected private keys must be unlocked with decryptKey() before decrypt().
const { createMessage, decrypt, encrypt, generateKey, readKey, readMessage, readPrivateKey } = require("node-rpgp");
const generated = generateKey();
const publicKey = readKey({ armoredKey: generated.publicKey });
const privateKey = readPrivateKey({ armoredKey: generated.privateKey });
const encrypted = encrypt({
message: createMessage({ text: "Zażółć gęślą jaźń" }),
encryptionKeys: publicKey,
});
const decrypted = decrypt({
message: readMessage({ armoredMessage: encrypted }),
decryptionKeys: privateKey,
});
console.log(decrypted.data);const encrypted = encrypt({
message: createMessage({ binary: new Uint8Array([0, 1, 2, 127, 128, 255]) }),
encryptionKeys: publicKey,
});
const decrypted = decrypt({
message: readMessage({ armoredMessage: encrypted }),
decryptionKeys: privateKey,
format: "binary",
});decrypted.data is a Uint8Array.
Thrown errors use stable code strings where possible:
type NodeRpgpErrorCode =
| "INVALID_INPUT"
| "INVALID_PUBLIC_KEY"
| "INVALID_PRIVATE_KEY"
| "INVALID_MESSAGE"
| "INVALID_PASSPHRASE"
| "DECRYPTION_FAILED"
| "ENCRYPTION_FAILED"
| "KEY_GENERATION_FAILED"
| "UNSUPPORTED_FEATURE";This package delegates implemented PGP operations to rPGP. It does not implement cryptographic primitives in JavaScript.
The API is synchronous and blocks the event loop. Do not use it with untrusted huge inputs on latency-sensitive request paths without input limits.
No security audit is claimed.
This is a native Node.js package. The release workflow targets Linux x64 glibc and Linux x64 musl artifacts.
MIT