denoland/deno · error · NodeError
ERR_CRYPTO_INVALID_KEYLEN
ERR_CRYPTO_INVALID_KEYLEN
Error message
Unspecified validation error
What it means
computeSecret (diffiehellman.ts:267) throws ERR_CRYPTO_INVALID_KEYLEN with message 'Unspecified validation error' when the peer public key buffer is empty. The length check runs before the native DH op, matching Node's rejection of zero-length peer keys; the code name is generic but here it always means 'empty otherPublicKey'.
Source
Thrown at ext/node/polyfills/internal/crypto/diffiehellman.ts:267
} else {
generator = this.#generator.readUint32BE();
}
if (generator != 2 && generator != 5) {
throw new NodeError("ERR_OSSL_DH_BAD_GENERATOR", "bad generator");
}
return generator;
}
computeSecret(
otherPublicKey: ArrayBufferView | string,
inputEncoding?: any,
outputEncoding?: any,
): Buffer | string {
const buf = getArrayBufferOrView(otherPublicKey, "key", inputEncoding);
if (buf.length === 0) {
throw new NodeError(
"ERR_CRYPTO_INVALID_KEYLEN",
"Unspecified validation error",
);
}
const sharedSecret = op_node_dh_compute_secret(
this.#prime,
this.#privateKey,
buf,
);
// Zero-pad the shared secret to the length of the prime, per RFC 4346
let secretBuf = Buffer.from(TypedArrayPrototypeGetBuffer(sharedSecret));
const primeLen = this.#prime.length;
if (secretBuf.length < primeLen) {
const padded = Buffer.alloc(primeLen);
secretBuf.copy(padded, primeLen - secretBuf.length);
secretBuf = padded;View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Decode and check peer key length > 0 before calling computeSecret
- Verify the input encoding matches how the peer serialized the key
- Validate handshake message shape (required fields present, lengths plausible) before the DH layer
Example fix
// before
const secret = dh.computeSecret(peerKeyB64, 'base64'); // empty input throws
// after
const peer = Buffer.from(peerKeyB64, 'base64');
if (peer.length === 0) throw new Error('empty peer public key');
const secret = dh.computeSecret(peer); Defensive patterns
Strategy: validation
Validate before calling
const peer = Buffer.from(otherPublicKey, inputEncoding);
if (peer.length === 0) throw new Error('empty peer public key');
const secret = dh.computeSecret(peer); Type guard
function isNonEmptyKeyBytes(v) { return (ArrayBuffer.isView(v) && v.byteLength > 0) || (typeof v === 'string' && v.length > 0); } Try / catch
try { secret = dh.computeSecret(peer); } catch (e) { if (e?.code === 'ERR_CRYPTO_INVALID_KEYLEN') { /* peer key was empty/corrupt — request retransmission */ } else throw e; } Prevention
- Validate handshake messages have a non-empty key field before touching DH
- Confirm both sides agree on the key encoding (base64 vs hex) before decoding
- Check decoded byte length against the expected size for the group/curve
When it happens
Trigger: dh.computeSecret('') or computeSecret(Buffer.alloc(0)); a peer key string that decoded (base64/hex) to zero bytes; undefined passed as otherPublicKey and coerced by getArrayBufferOrView into empty input.
Common situations: Handshake messages with a missing key field; encoding mismatch (peer sent hex, receiver decodes base64) yielding empty/garbage output; truncated key-exchange payloads over the wire.
Related errors
- ERR_INVALID_ARG_TYPE
- ERR_OSSL_DH_MODULUS_TOO_SMALL
- ERR_OSSL_DH_BAD_GENERATOR
- ERR_CRYPTO_UNKNOWN_DH_GROUP
- Invalid key type
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/4c91c4d5f0fdd966.
Report an issue: GitHub.