gchq/CyberChef · error · OperationError

${err.toString()}

Error message

${err.toString()}

What it means

Generic catch-all thrown by BcryptCompare.run when bcrypt.compare rejects its arguments rather than resolving to false. bcrypt.compare expects a valid bcrypt hash string as its second argument (the hash from args[0]); if that hash is malformed (wrong version prefix, bad cost, invalid base64 salt, truncated), bcrypt throws and the original Error.toString() is forwarded. A genuine non-match resolves to false and yields 'No match', not this error.

Source

Thrown at src/core/operations/BcryptCompare.mjs:55

    }

    /**
     * @param {string} input
     * @param {Object[]} args
     * @returns {string}
     */
    async run(input, args) {
        const hash = args[0];

        let match;
        try {
            match = await bcrypt.compare(input, hash, undefined, p => {
                // Progress callback
                if (isWorkerEnvironment())
                    self.sendStatusMessage(`Progress: ${(p * 100).toFixed(0)}%`);
            });
        } catch (err) {
            throw new OperationError(err.toString());
        }

        return match ? "Match: " + input : "No match";

    }

}

export default BcryptCompare;

View on GitHub (pinned to 4290ea7539)

Solutions

  1. Ensure the hash argument is a full, valid bcrypt hash (e.g. $2b$12$... 60 characters).
  2. Trim whitespace/newlines from the stored hash before comparing.
  3. If you have a non-bcrypt hash, use the matching verify operation instead.
  4. Distinguish this error (malformed hash) from a normal 'No match' result (valid hash, wrong password).

Example fix

// before - truncated/malformed hash
chef.bcryptCompare("pw", "$2b$12$abc");

// after - full 60-char bcrypt hash
chef.bcryptCompare("pw", "$2b$12$abcdefghijklmnopqrstuuVXQ1Nh2yTLB07h2yTLB07h2yTLB07h");
Defensive patterns

Strategy: validation

Validate before calling

const BCRYPT_HASH_RE = /^\$2[aby]\$\d{2}\$[./A-Za-z0-9]{53}$/;
function assertBcryptHash(hash) {
  const h = String(hash).trim();
  if (!BCRYPT_HASH_RE.test(h)) {
    throw new Error("Not a valid bcrypt hash (expected $2a/$2b/$2y$<cost>$<53 base64 chars>)");
  }
  return h;
}
assertBcryptHash(hash);

Type guard

function isBcryptHash(s) {
  return /^\$2[aby]\$\d{2}\$[./A-Za-z0-9]{53}$/.test(String(s).trim());
}

Try / catch

try {
  await chef.bcryptCompare(input, hash);
} catch (e) {
  if (/illegal|invalid|hash|salt/i.test(e.message)) {
    throw new Error(`Stored hash is not a valid bcrypt hash: ${e.message}`);
  }
  throw e;
}

Prevention

When it happens

Trigger: Passing a hash that is not a $2a$/$2b$/$2y$ bcrypt string, a hash with a missing or invalid cost factor, a corrupted base64 salt section, or a hash truncated below the 60-character minimum.

Common situations: Comparing against an MD5/SHA hash by mistake; hash copied incompletely (bcrypt hashes are 60 chars); version prefix stripped during copy; whitespace/newline accidentally included in the stored hash.

Related errors


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