denoland/deno · error · Error
operation not supported for this keytype
Error message
operation not supported for this keytype
What it means
checkUnsupportedKeyType (cipher.ts:778) runs at the top of privateEncrypt, privateDecrypt, publicEncrypt and publicDecrypt. If the key's asymmetricKeyType is one of rsa-pss, dsa, ec, ed25519, ed448, x25519 or x448, it throws the plain Error 'operation not supported for this keytype'. These four operations are RSA primitives; the blocklist mirrors the key types OpenSSL refuses for RSA padding schemes.
Source
Thrown at ext/node/polyfills/internal/crypto/cipher.ts:778
}
}
const ENCRYPT_UNSUPPORTED_KEY_TYPES = new SafeSet([
"rsa-pss",
"dsa",
"ec",
"ed25519",
"ed448",
"x25519",
"x448",
]);
function checkUnsupportedKeyType(key) {
const keyType = isKeyObject(key)
? key.asymmetricKeyType
: key?.key?.asymmetricKeyType;
if (keyType && SetPrototypeHas(ENCRYPT_UNSUPPORTED_KEY_TYPES, keyType)) {
throw new Error("operation not supported for this keytype");
}
}
const WEBCRYPTO_SHA_HYPHEN_RE = new SafeRegExp("^(sha)-(?!3-)");
function normalizeOaepHash(hash: unknown): string | undefined {
if (hash === undefined) return undefined;
if (typeof hash !== "string") {
throw new ERR_INVALID_ARG_TYPE("oaepHash", "string", hash);
}
if (!hash) return undefined;
// Normalize to lowercase and strip WebCrypto-style hyphens
// (e.g. "SHA-256" -> "sha256") but keep sha3/sha512 sub-variants
// (e.g. "sha3-256", "sha512-224") intact.
const normalized = StringPrototypeReplace(
StringPrototypeToLowerCase(hash),
WEBCRYPTO_SHA_HYPHEN_RE,
"$1",View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Use an RSA key pair (createPublicKey/createPrivateKey over PEM/PKCS#8) for publicEncrypt/privateDecrypt
- For EC/Ed25519/Ed448 material, switch to the operations those keys support: sign/verify (ECDSA/EdDSA)
- For x25519/x448, use crypto.diffieHellman({ privateKey, publicKey }) instead of encrypt/decrypt
- If the key is rsa-pss, load an rsa (PKCS#1) key instead — rsa-pss is on the reject list
Example fix
// before
const { publicKey } = generateKeyPairSync('ed25519');
publicEncrypt(publicKey, data); // operation not supported for this keytype
// after
const { publicKey, privateKey } = generateKeyPairSync('rsa', { modulusLength: 2048 });
const ct = publicEncrypt(publicKey, data);
const pt = privateDecrypt(privateKey, ct); Defensive patterns
Strategy: type-guard
Validate before calling
import { isKeyObject } from 'node:crypto';
function assertRsaKeyForEncrypt(key) {
const t = isKeyObject(key) ? key.asymmetricKeyType : key?.key?.asymmetricKeyType;
if (t && t !== 'rsa') throw new TypeError(`key type ${t} is not usable for RSA encrypt/decrypt`);
} Type guard
function usableForRsaOps(key) {
const t = key?.asymmetricKeyType ?? key?.key?.asymmetricKeyType;
return t == null || t === 'rsa';
} Try / catch
try { publicEncrypt(key, data); } catch (e) { if (e.message === 'operation not supported for this keytype') { /* fetch/generate an RSA key instead */ } else throw e; } Prevention
- Assert asymmetricKeyType === 'rsa' before any public/private encrypt/decrypt call
- Keep a key-usage registry: which key ids are for signing vs encryption vs key agreement
- Unit-test key loading with the exact PEMs used in production
When it happens
Trigger: crypto.publicEncrypt(ed25519PublicKey, data); crypto.privateDecrypt({ key: ecKey }, ct); loading an rsa-pss key from a certificate and calling publicDecrypt; passing an x25519 key from an ECDH flow into RSA encrypt/decrypt.
Common situations: Mixing WebCrypto-generated Ed25519/EC key pairs with node:crypto RSA APIs; keys provisioned for signing reused for encryption; certificate-based key loading where the cert carries an EC or rsa-pss key.
Related errors
- Invalid key type
- ERR_CRYPTO_ECDH_INVALID_PUBLIC_KEY
- Failed to get ECDH private key
- Failed to get ECDH public key
- PBKDF2 keys are not extractable
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/e1d0ff16a0f4d272.
Report an issue: GitHub.