passbolt/passbolt_api · critical · InternalErrorException

The OpenPGP server key defined in the config cannot be used…

Error message

The OpenPGP server key defined in the config cannot be used to decrypt. {exception->getMessage()}

What it means

Thrown by GpgAuthenticator::_initKeyring() when the fingerprint is valid but the OpenPGP backend cannot set the server key as decryption key: the key material is not importable into the GnuPG keyring or the passphrase does not unlock it. The original exception message is appended to aid diagnosis. Reported as InternalErrorException (HTTP 500).

Solutions

  1. Read the appended exception message to identify the root cause (import failure vs bad passphrase).
  2. Confirm the private key file exists, is readable by the web server user, and its fingerprint matches passbolt.gpg.serverKey.fingerprint (gpg --homedir ... --fingerprint).
  3. Fix passbolt.gpg.serverKey.passphrase to the actual key passphrase (empty string if none).
  4. Ensure the GnuPG home directory is writable and consistent (permissions ~700, correct GNUPGHOME), then retry; re-import the key pair if the keyring is stale.

Example fix

// before
'passbolt.gpg.serverKey.passphrase' => 'wrong-pass',

// after
'passbolt.gpg.serverKey.passphrase' => env('PASSBOLT_GPG_SERVERKEY_PASSPHRASE', ''),
Defensive patterns

Strategy: validation

Validate before calling

// Before serving requests, verify the key is usable:
$gpg = OpenPGPBackendFactory::get();
try {
    $gpg->setDecryptKeyFromFingerprint(
        Configure::read('passbolt.gpg.serverKey.fingerprint'),
        Configure::read('passbolt.gpg.serverKey.passphrase')
    );
} catch (Exception $e) { /* fail fast at boot */ }

Try / catch

try {
    $gpg->setDecryptKeyFromFingerprint($fingerprint, $passphrase);
} catch (Exception $e) {
    // inspect $e->getMessage(): key import vs passphrase problem
}

Prevention

When it happens

Trigger: During any GPGAuth request, setDecryptKeyFromFingerprint($fingerprint, $passphrase) throws (key absent from keyring, corrupt key file, wrong passphrase); the fallback importServerKeyInKeyring() + retry also throws, so the exception is wrapped and rethrown with its message appended.

Common situations: serverkey.private.asc missing or unreadable by the web user; GPG homedir (GNUPGHOME) not writable or pointing elsewhere; passphrase in config does not match the one the key was generated with; key was regenerated on disk but the config fingerprint still references the old key; GnuPG agent cache/lock issues in containers.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at src/Authenticator/GpgAuthenticator.php:349

        $fingerprint = Configure::read('passbolt.gpg.serverKey.fingerprint');
        $passphrase = Configure::read('passbolt.gpg.serverKey.passphrase');

        // Check if config contains fingerprint
        if (!is_string($fingerprint) || !PublicKeyValidationService::isValidFingerprint($fingerprint)) {
            throw new InternalErrorException('The GnuPG config for the server is not available or incomplete.');
        }

        // set the key to be used for decrypting
        try {
            $this->_gpg->setDecryptKeyFromFingerprint($fingerprint, $passphrase);
        } catch (Exception $exception) {
            try {
                $this->_gpg->importServerKeyInKeyring();
                $this->_gpg->setDecryptKeyFromFingerprint($fingerprint, $passphrase);
            } 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);
            }
        }
    }

    /**
     * Set user key for encryption and import it in the keyring if needed
     *
     * @param string $fingerprint fingerprint
     * @throws \Cake\Http\Exception\InternalErrorException when the key is not valid
     * @return void
     */
    private function _initUserKey(string $fingerprint): void
    {
        try {
            $this->_gpg->setEncryptKeyFromFingerprint($fingerprint);
        } catch (Exception $exception) {
            // Try to import the key in keyring again
            try {

View on GitHub (pinned to 31c1bbc10f)