passbolt/passbolt_api · critical · Cake\Http\Exception\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. 

What it means

setServerKey imports the configured OpenPGP server key into the GnuPG keyring and registers it as decrypt/sign key during authenticator init. If any of those gnupg operations throws, the message is prefixed with 'The OpenPGP server key defined in the config cannot be used to decrypt.' plus the underlying exception message, and rethrown as InternalErrorException. The JWT flow cannot proceed without a usable server key.

Solutions

  1. Read the appended underlying exception message in the response/log — it names the exact gnupg failure.
  2. Verify the server key fingerprint and passphrase in config match the actual key files, and that both public and private key files exist and are readable.
  3. Regenerate or re-import the server key into the keyring (e.g. passbolt serverkey commands / gpg --import as the web user).
  4. Check the GNUPGHOME directory (~/.gnupg of the web-server user) exists, is writable, and gpg binary is installed.
  5. Ensure the passphrase in config is correct for the private key.

Example fix

// before (config): wrong fingerprint/passphrase
'fingerprint' => 'ABCD1234...',
'passphrase' => '',

// after: matching values for the imported key
'fingerprint' => strtoupper(str_replace(' ', '', $realFingerprint)),
'passphrase' => $actualKeyPassphrase
Defensive patterns

Strategy: validation

Validate before calling

// healthcheck before auth flows
const ok = await fetch('/healthcheck/status.json').then(r => r.json());
if (!ok.body.gpg) throw new Error('Server GPG key not functional — fix config/keyring first');

Try / catch

try { await jwtLogin(); } catch (e) { if (e.message.includes('cannot be used to decrypt')) reportServerConfigIssue(e.message); else throw e; }

Prevention

When it happens

Trigger: JWT authentication bootstrap when: the server key fingerprint/passphrase in config is wrong; the key files (serverkey.asc / serverkey_private.asc) are missing or unreadable; the key cannot be imported into the keyring; the passphrase is incorrect; GnuPG is missing or the GNUPGHOME is not writable.

Common situations: Fresh deployments where `passbolt create_user`/serverkey generation step was skipped; wrong 'passbolt.gpg.keyring' or JWT server key config after migrating servers; keyring permission issues under the web-server user (www-data); passphrase changed in config but not on the key.

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/6864cfbb00c6a215. Report an issue: GitHub.

Appendix: source

Thrown at plugins/PassboltCe/JwtAuthentication/src/Authenticator/GpgJwtAuthenticator.php:220

        $this->assertServerFingerprint($fingerprint);

        // Check if config contains valid passphrase
        $passphrase = Configure::read('passbolt.gpg.serverKey.passphrase');
        $this->assertServerPassphrase($passphrase);

        // set the key to be used for decrypting
        try {
            $this->gpg->setSignKeyFromFingerprint($fingerprint, $passphrase);
            $this->gpg->setDecryptKeyFromFingerprint($fingerprint, $passphrase);
        } catch (Exception $exception) {
            try {
                $this->gpg->importServerKeyInKeyring();
                $this->gpg->setSignKeyFromFingerprint($fingerprint, $passphrase);
                $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
     *
     * @throws \Cake\Http\Exception\BadRequestException if the user data is not valid
     * @throws \Cake\Http\Exception\InternalErrorException if the user key cannot be loaded
     * @return void
     */
    public function setUserKey(): void
    {
        try {
            $this->gpg->setVerifyKeyFromFingerprint($this->user->gpgkey->fingerprint);
            $this->gpg->setEncryptKeyFromFingerprint($this->user->gpgkey->fingerprint);
        } catch (Exception $exception) {
            // Try to import the key in keyring again

View on GitHub (pinned to 31c1bbc10f)