gchq/CyberChef · error · OperationError

Couldn't decrypt message with provided private key: ${err}

Error message

Couldn't decrypt message with provided private key: ${err}

What it means

Catch-all around kbpgp.unbox in PGPDecrypt.run. The private key imported fine (importPrivateKey succeeded and unlocked), but unboxing the armoured message failed - wrong key for this message, corrupt/truncated ciphertext, a message not encrypted for this key, or an incompatible OpenPGP packet structure. The underlying kbpgp error is appended after the colon.

Source

Thrown at src/core/operations/PGPDecrypt.mjs:79

    async run(input, args) {
        const encryptedMessage = input,
            [privateKey, passphrase] = args,
            keyring = new kbpgp.keyring.KeyRing();
        let plaintextMessage;

        if (!privateKey) throw new OperationError("Enter the private key of the recipient.");

        const key = await importPrivateKey(privateKey, passphrase);
        keyring.add_key_manager(key);

        try {
            plaintextMessage = await promisify(kbpgp.unbox)({
                armored: encryptedMessage,
                keyfetch: keyring,
                asp: ASP
            });
        } catch (err) {
            throw new OperationError(`Couldn't decrypt message with provided private key: ${err}`);
        }

        return plaintextMessage.toString();
    }

}

export default PGPDecrypt;

View on GitHub (pinned to 4290ea7539)

Solutions

  1. Confirm the private key is the exact counterpart of the public key the message was encrypted for.
  2. Re-enter the passphrase and verify the key unlocks correctly.
  3. Re-export or re-armour the message to rule out truncation.
  4. Decrypt locally with GnuPG to confirm the message + key pair is valid before blaming CyberChef/kbpgp.
Defensive patterns

Strategy: try-catch

Validate before calling

if (!/-----BEGIN PGP MESSAGE-----/.test(encryptedMessage)) {
    throw new Error('Input is not an armoured PGP message.');
}
if (!/-----BEGIN PGP PRIVATE KEY BLOCK-----/.test(privateKey)) {
    throw new Error('Argument is not an armoured PGP private key.');
}

Try / catch

try {
    plaintext = await chef.PGPDecrypt(message, [privKey, pass]);
} catch (e) {
    if (e instanceof OperationError && /Couldn't decrypt/.test(e.message)) {
        // key/message mismatch - surface e.message to the user
    } else throw e;
}

Prevention

When it happens

Trigger: Private key does not correspond to the message recipient (no matching key packet); message uses an algorithm/feature kbpgp cannot handle; armoured message is malformed or truncated; passphrase was wrong yet produced a key that silently fails to match session keys.

Common situations: Using a public key to encrypt but the actual private key differs/has rotated; passphrase typo; cross-tool messages (GnuPG v2 SEIPD/AEAD features) kbpgp does not parse; message truncated in transit.

Related errors


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