passbolt/passbolt_api · critical · InternalErrorException

500

500

Error message

The OpenPGP server key defined in the config cannot be used to decrypt. 

What it means

DirectoryOrgSettings::encrypt signs/encrypts the directory settings payload with the server OpenPGP key. If loading the sign/encrypt key from the configured fingerprint fails (bad fingerprint, missing keyring, wrong passphrase), the original exception is wrapped into an InternalErrorException with this message, HTTP 500.

Solutions

  1. Verify passbolt.gpg.serverKey.fingerprint matches a key present in the web server user's keyring (`gpg --list-keys --homedir $GNUPGHOME`)
  2. Re-import the server key pair into the keyring and set correct ownership/permissions on GNUPGHOME
  3. Check the configured passphrase (passbolt.gpg.serverKey.passphrase) is correct for the key
  4. Run `ddev exec su -m -c "bin/cake passbolt healthcheck" www-data` or the GPG healthcheck to validate the key setup

Example fix

// config/passbolt.php
// before
'serverKey' => [
    'fingerprint' => '2FC8945813C4883A68FA4E1D2A4B7E30XXXXXXXX',
    'passphrase' => 'wrong-passphrase',
],
// after
'serverKey' => [
    'fingerprint' => '2FC8945813C4883A68FA4E1D2A4B7E30AAAAAAAA', // fingerprint from gpg --list-keys
    'passphrase' => 'correct-passphrase',
],
Defensive patterns

Strategy: validation

Validate before calling

$fp = Configure::read('passbolt.gpg.serverKey.fingerprint');
$gpg = new gnupg();
$gpg->sethomedir(Configure::read('passbolt.gpg.keyring'));
$info = $gpg->keyinfo($fp);
if (empty($info)) { /* key missing: import before saving settings */ }

Try / catch

try {
    $settings->save($data);
} catch (InternalErrorException $e) {
    $this->log($e->getMessage());
    return $this->respondWithError('500', __('Server OpenPGP key is misconfigured; verify fingerprint, keyring and passphrase.'));
}

Prevention

When it happens

Trigger: Calling save() on DirectoryOrgSettings when passbolt.gpg.serverKey fingerprint is wrong, the key is absent from the GNUPG keyring, or the passphrase is incorrect, making setSignKeyFromFingerprint/setEncryptKeyFromFingerprint throw.

Common situations: Server key regenerated or rotated without updating config; GNUPGHOME not writable/missing for the web server user; fingerprint casing/whitespace typo in config; moving to a new server without importing the key.

Related errors


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

Appendix: source

Thrown at plugins/PassboltEe/DirectorySync/src/Utility/DirectoryOrgSettings.php:459

        $gpgConfig = Configure::read('passbolt.gpg');
        $fingerprint = $gpgConfig['serverKey']['fingerprint'];
        $passphrase = $gpgConfig['serverKey']['passphrase'];
        $gpg = OpenPGPBackendFactory::get();

        try {
            $gpg->setSignKeyFromFingerprint($fingerprint, $passphrase);
            $gpg->setEncryptKeyFromFingerprint($fingerprint);
        } catch (Exception $exception) {
            try {
                // Try again by importing key into keyring
                $gpg->importServerKeyInKeyring();
                $gpg->setSignKeyFromFingerprint($fingerprint, $passphrase);
                $gpg->setEncryptKeyFromFingerprint($fingerprint);
            } catch (Exception $exception) {
                $msg = __('The OpenPGP server key defined in the config cannot be used to decrypt.') . ' ';
                $msg .= $exception->getMessage();

                throw new InternalErrorException($msg, 500, $exception);
            }
        }

        return $gpg->encrypt($data, true);
    }

    /**
     * Decrypt the organization settings
     *
     * @param string $data The message to decrypt
     * @return string
     */
    protected static function decrypt(string $data): string
    {
        $gpgConfig = Configure::read('passbolt.gpg');
        $keyid = $gpgConfig['serverKey']['fingerprint'];
        $passphrase = $gpgConfig['serverKey']['passphrase'];
        $gpg = OpenPGPBackendFactory::get();

View on GitHub (pinned to 31c1bbc10f)