denoland/deno · error · TypeError
Algorithm must be specified when using non-Ed25519 keys
Error message
Algorithm must be specified when using non-Ed25519 keys
What it means
One-shot crypto.sign() with a non-Ed25519/Ed448 key requires an explicit digest. The only default is an rsa-pss key whose stored key details include a hashAlgorithm; for every other key type (rsa, ecdsa, dsa, rsa-pss without an embedded hash) algorithm == null throws this TypeError.
Source
Thrown at ext/node/polyfills/internal/crypto/sig.ts:439
if (
ObjectPrototypeIsPrototypeOf(Uint8ArrayPrototype, ctx) &&
ctx.length > 0
) {
throw new TypeError("Context parameter is unsupported");
}
result = new FastBuffer(114);
op_node_sign_ed448(handle, dataBytes, result);
} else {
let digest = algorithm;
if (digest == null) {
if (keyType === "rsa-pss") {
const details = op_node_get_asymmetric_key_details(handle);
if (details.hashAlgorithm) {
digest = details.hashAlgorithm;
}
}
if (digest == null) {
throw new TypeError(
"Algorithm must be specified when using non-Ed25519 keys",
);
}
}
// Preserve padding/saltLength options from the original key
const privateKeyObject = new PrivateKeyObject(handle);
const signKey = typeof key === "object" &&
!(ObjectPrototypeIsPrototypeOf(KeyObject.prototype, key))
? { ...key, key: privateKeyObject }
: privateKeyObject;
result = Sign(digest).update(dataBytes)
.sign(signKey);
}
if (callback) {
setTimeout(() => callback(null, result));
} else {
return result;View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Pass an explicit digest: crypto.sign("sha256", data, key).
- Branch by key.asymmetricKeyType — null only for ed25519/ed448 (and rsa-pss with embedded hash).
- When generating rsa-pss keys, set hashAlgorithm so the embedded default applies.
Example fix
// before const sig = crypto.sign(null, data, key); // throws for RSA/ECDSA keys // after const alg = key.asymmetricKeyType === "ed25519" || key.asymmetricKeyType === "ed448" ? null : "sha256"; const sig = crypto.sign(alg, data, key);
Defensive patterns
Strategy: validation
Validate before calling
function requiredDigest(key, requested) {
if (requested != null) return requested;
const t = key.asymmetricKeyType ?? key.key?.asymmetricKeyType;
if (t === "ed25519" || t === "ed448") return null;
throw new Error(`an explicit digest (e.g. "sha256") is required for ${t} keys`);
}
const sig = crypto.sign(requiredDigest(key, alg), data, key); Type guard
const needsExplicitDigest = (key) => {
const t = key.asymmetricKeyType ?? key.key?.asymmetricKeyType;
return t !== "ed25519" && t !== "ed448" && t !== "rsa-pss"; // rsa-pss may carry its own hash
}; Try / catch
try {
sig = crypto.sign(digest, data, key);
} catch (e) {
if (e instanceof TypeError && /Algorithm must be specified/.test(e.message)) {
throw new Error(`digest required for key type ${key.asymmetricKeyType}`);
}
throw e;
} Prevention
- Only pass null for ed25519/ed448 (or rsa-pss keys generated with an embedded hashAlgorithm).
- Centralize the key-type-to-digest mapping in one function used by both sign paths.
- When generating rsa-pss keys, always set hashAlgorithm so a sensible default exists.
When it happens
Trigger: crypto.sign(null, data, rsaPrivateKey); crypto.sign(null, data, ecdsaKey); copy-pasted ed25519 example code (which passes null) reused with RSA or EC keys.
Common situations: Key-agnostic signing helpers that pass null because it works for ed25519; code written against rsa-pss keys with embedded hashes then pointed at plain RSA keys; WebCrypto ports where the hash was part of the key rather than the call.
Related errors
- Invalid digest: ${algorithm}
- no default digest
- ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE
- ERR_INVALID_ARG_VALUE
- ERR_CRYPTO_SIGN_KEY_REQUIRED
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/0b94b6ec668003a6.
Report an issue: GitHub.