passbolt/passbolt_api · critical · Cake\Core\Exception\CakeException

Decryption failed.

Error message

Decryption failed.

What it means

Thrown when the gnupg extension's decrypt() or decryptverify() call throws while decrypting an armored message with the server private key. The backend clears the decrypt keys and rethrows as 'Decryption failed.' plus the gnupg error message.

Solutions

  1. Confirm the private key matching the recipient of the message is in the keyring and passphrase-less: gpg --list-secret-keys
  2. Restore/rotate: re-import the old private key or decrypt legacy data before rotating passbolt.gpg.serverKey
  3. Validate the armored input (no HTML entity mangling/truncation) before calling decrypt
  4. Check GNUPGHOME permissions and that gpg-agent is running for the PHP user

Example fix

// before
$decrypted = $gpg->decrypt($corruptedOrWrongKeyMessage); // CakeException: Decryption failed. ...
// after
$gpg->setDecryptKey($correctServerKeyFingerprint);
$decrypted = $gpg->decrypt($validArmoredMessage);
Defensive patterns

Strategy: try-catch

Validate before calling

if (!str_contains($armored, '-----BEGIN PGP MESSAGE-----')) {
    throw new InvalidArgumentException('Payload is not an armored PGP message');
}
$hasSecret = str_contains((string) shell_exec('gpg --list-secret-keys --with-colons'), $serverFingerprint);

Try / catch

try {
    $plain = $gpg->decrypt($armored);
} catch (CakeException $e) {
    $this->log('Decrypt failed: ' . $e->getMessage());
    throw new DecryptionException('Stored secret cannot be decrypted with current server key.', 0, $e);
}

Prevention

When it happens

Trigger: decrypt($text) where the ciphertext is corrupt/not valid OpenPGP, was encrypted for a different key, or the private key in the keyring is missing, passphrase-protected, or inaccessible.

Common situations: Data encrypted with a previous/rotated server key while the old private key was deleted; server key file re-imported with a passphrase; truncated or modified armored payload; keyring on read-only/incorrect-permission homedir; POST body corruption (encoding issues).

Related errors


AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17). Data as JSON: /api/errors/4a1d68fe3c99ea16. Report an issue: GitHub.

Appendix: source

Thrown at src/Utility/OpenPGP/Backends/Gnupg.php:398

        $decrypted = false;
        $fingerprint = null;
        $signatureInfo = null;
        $this->assertDecryptKey();
        if ($verifySignature) {
            $this->assertVerifyKey();
            $fingerprint = $this->_verifyKeyFingerprint;
            $this->clearVerifyKeys();
        }
        try {
            if ($verifySignature === false) {
                $decrypted = $this->_gpg->decrypt($text);
            } else {
                /** @psalm-suppress InvalidArgument  */
                $signatureInfo = $this->_gpg->decryptverify($text, $decrypted);
            }
        } catch (Exception $e) {
            $this->clearDecryptKeys();
            throw new CakeException(__('Decryption failed.') . ' ' . $e->getMessage(), null, $e);
        }
        $this->clearDecryptKeys();

        if ($decrypted === false) {
            throw new CakeException(__('Decryption failed.'));
        }
        if ($verifySignature) {
            if (empty($signatureInfo) || $signatureInfo[0]['fingerprint'] !== $fingerprint) {
                $msg = __('Expected {0} and got {1}.', $fingerprint, $signatureInfo[0]['fingerprint']);
                $msg = __('Decryption failed. Invalid signature.') . ' ' . $msg;
                throw new CakeException($msg);
            }
        }

        return $decrypted;
    }

    /**

View on GitHub (pinned to 31c1bbc10f)