gchq/CyberChef · error · OperationError

Not enough data in Server Hello.

Error message

Not enough data in Server Hello.

What it means

JA3SFingerprint reads the 3-byte handshake length and requires total stream length === handshakeLength + 9. A mismatch means the ServerHello body is truncated or carries extra bytes. readInt returning undefined on short input also satisfies the !== check.

Source

Thrown at src/core/operations/JA3SFingerprint.mjs:82

            throw new OperationError("Not handshake data.");

        // Version
        s.moveForwardsBy(2);

        // Length
        const length = s.readInt(2);
        if (s.length !== length + 5)
            throw new OperationError("Incorrect handshake length.");

        // Handshake type
        const handshakeType = s.readInt(1);
        if (handshakeType !== 2)
            throw new OperationError("Not a Server Hello.");

        // Handshake length
        const handshakeLength = s.readInt(3);
        if (s.length !== handshakeLength + 9)
            throw new OperationError("Not enough data in Server Hello.");

        // Hello version
        const helloVersion = s.readInt(2);

        // Random
        s.moveForwardsBy(32);

        // Session ID
        const sessionIDLength = s.readInt(1);
        s.moveForwardsBy(sessionIDLength);

        // Cipher suite
        const cipherSuite = s.readInt(2);

        // Compression Method
        s.moveForwardsBy(1);

        // Extensions

View on GitHub (pinned to 4290ea7539)

Solutions

  1. Ensure the full ServerHello body is present (handshakeLength bytes after the 4-byte handshake header).
  2. Match inputFormat so the 3-byte length is correct.
  3. Re-capture the ServerHello including all extensions.
  4. Trim the input to exactly handshakeLength + 9 bytes.

Example fix

// before
ja3s.run(truncatedServerHello, ['Hex','Base64']); // length mismatch -> Not enough data.
// after
const full = await recaptureFullServerHello();
ja3s.run(full, ['Hex','Base64']);
Defensive patterns

Strategy: validation

Validate before calling

import Utils from "src/core/Utils.mjs";
function assertFullServerHello(input, inputFormat) {
  const b = Utils.convertToByteArray(input, inputFormat);
  if (b.length < 9) throw new Error('record too short for handshake header');
  const hsLen = (b[6] << 16) | (b[7] << 8) | b[8];
  if (b.length !== hsLen + 9) {
    throw new Error(`Stream length ${b.length} != handshake length ${hsLen}+9. ServerHello is truncated or has extra bytes.`);
  }
  return b;
}

Type guard

function isCompleteServerHello(bytes) {
  if (bytes.length < 9) return false;
  const hsLen = (bytes[6] << 16) | (bytes[7] << 8) | bytes[8];
  return bytes[0] === 0x16 && bytes[5] === 2 && bytes.length === hsLen + 9;
}

Prevention

When it happens

Trigger: A truncated ServerHello (missing session ID / cipher suite / compression / extensions), a handshake length field corrupted by inputFormat mismatch, or extra bytes inside the declared record length. Parsing of the body fields has not started, so this is purely a size check.

Common situations: Truncated paste of a ServerHello, capture missing the extensions tail, inputFormat mismatch corrupting the 3-byte length, or an unusual TLS 1.3 ServerHello layout.

Related errors


AI-assisted analysis of gchq/CyberChef@4290ea7539 (2026-08-13). Data as JSON: /api/errors/2b076bffbe2753a4. Report an issue: GitHub.