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

Decryption failed. Invalid signature. Expected

Error message

Decryption failed. Invalid signature. Expected {0} and got {1}.

What it means

Thrown when decrypt($text, true) succeeds but the signature embedded in the message does not match the verify key fingerprint set via setVerifyKey. It reports 'Decryption failed. Invalid signature. Expected {0} and got {1}.' — the message decrypted, but was not signed by the expected key.

Solutions

  1. Compare the 'got' fingerprint in the message with your configured verify key; if the server key rotated, set the new/old key accordingly via setVerifyKey before decrypt
  2. If legitimate, re-sign or re-encrypt the data with the current server key
  3. If the sender should differ, pass the expected signer's fingerprint as verify key
  4. Treat as integrity failure — do not trust the decrypted content in security-sensitive flows

Example fix

// before
$gpg->setVerifyKey($newServerKeyFingerprint);
$plain = $gpg->decrypt($msgSignedWithOldKey, true); // Invalid signature. Expected new, got old
// after
$gpg->setVerifyKey($oldSigningKeyFingerprint); // fingerprint that actually signed
$plain = $gpg->decrypt($msgSignedWithOldKey, true);
Defensive patterns

Strategy: try-catch

Validate before calling

// caller should know the expected signer fingerprint and compare
$expectedSigner = $this->getExpectedSignerFingerprint($context);
if ($expectedSigner !== $configuredVerifyFingerprint) {
    $gpg->setVerifyKey($expectedSigner);
}

Try / catch

try {
    $plain = $gpg->decrypt($armored, true);
} catch (CakeException $e) {
    if (str_contains($e->getMessage(), 'Invalid signature')) {
        $this->log('Signature from unexpected key — possible key rotation or tampering');
    }
    throw $e;
}

Prevention

When it happens

Trigger: decrypt with $verifySignature = true where signatureInfo is empty (message unsigned) or signatureInfo[0]['fingerprint'] differs from $this->_verifyKeyFingerprint.

Common situations: Verifying that a token/message was signed by the server itself but the data was signed by a user key or a different server key (after key rotation); verifying data signed by an older server key not set as verify key; attacker-substituted or replayed payloads.

Related errors


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

Appendix: source

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

                $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;
    }

    /**
     * Verify a signed message.
     *
     * @param string $signedText The signed message to verify.
     * @param string|null $plainText (optional) if this parameter is passed, it will be filled with the plain text.
     * @return array signature information
     * @throws \Cake\Core\Exception\CakeException If the armored signed message cannot be verified.
     */
    public function verify(string $signedText, ?string &$plainText = null): array
    {
        $this->assertVerifyKey();
        $msg = __('The message cannot be verified.');

View on GitHub (pinned to 31c1bbc10f)