{"record":{"id":"1a2fbfa41feb81f7","repo":"passbolt/passbolt_api","slug":"there-is-an-issue-with-the-openpgp-server-key-the","errorCode":null,"errorMessage":"There is an issue with the OpenPGP server key. The fingerprint does not match the one associated with the key on file.","messagePattern":"There is an issue with the OpenPGP server key\\. The fingerprint does not match the one associated with the key on file\\.","errorType":"exception","errorClass":"Cake\\Http\\Exception\\InternalErrorException","httpStatus":500,"severity":"critical","filePath":"src/Utility/OpenPGP/OpenPGPBackend.php","lineNumber":113,"sourceCode":"            $msg = __('The OpenPGP server key defined in the config is not found in the file system.');\n            throw new InternalErrorException($msg);\n        }\n        $privateKey = file_get_contents($keyFilePath);\n        if ($privateKey === false) {\n            $msg = __('The OpenPGP server key defined in the config cannot be opened.');\n            throw new InternalErrorException($msg);\n        }\n        if (!$this->isParsableArmoredPrivateKey($privateKey)) {\n            $msg = __('The OpenPGP server key defined on file is not a valid private key.');\n            throw new InternalErrorException($msg);\n        }\n\n        // try to import it\n        $this->importKeyIntoKeyring($privateKey);\n        if (!$this->isKeyInKeyring($fingerprint)) {\n            $msg = __('There is an issue with the OpenPGP server key.') . ' ';\n            $msg .= __('The fingerprint does not match the one associated with the key on file.');\n            throw new InternalErrorException($msg);\n        }\n    }\n\n    /**\n     * Check if a message is valid.\n     *\n     * To do this, we try to unarmor the message. If the operation is successful, then we consider that\n     * the message is a valid one.\n     *\n     * @param string $armored ASCII armored message data\n     * @return bool true if valid, false otherwise\n     */\n    public function isValidMessage(string $armored): bool\n    {\n        try {\n            $this->assertGpgMarker($armored, self::MESSAGE_MARKER);\n        } catch (CakeException $e) {\n            return false;","sourceCodeStart":95,"sourceCodeEnd":131,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/src/Utility/OpenPGP/OpenPGPBackend.php#L95-L131","documentation":"The key file was read and parsed as an armored private key and imported into the keyring, but isKeyInKeyring($fingerprint) then fails: the fingerprint configured in config does not match the fingerprint of the key actually on file. importServerKeyInKeyring treats this as a fatal server-key mismatch.","triggerScenarios":"importServerKeyInKeyring() imports the private key from file, then isKeyInKeyring($fingerprint) returns false because passbolt.gpg.serverKey.fingerprint differs from the key in the file (typo, stale fingerprint after key rotation, uppercase/lowercase or space formatting handled but wrong value).","commonSituations":"Server key was regenerated but config still holds the old fingerprint; fingerprint copied with/without spaces inconsistently between config sources (env var vs passbolt.php); multiple environments sharing one key file with different fingerprints.","solutions":["Get the true fingerprint: `gpg --show-keys <serverkey_private.asc>` (or `gpg --fingerprint <keyid>`) and set passbolt.gpg.serverKey.fingerprint to exactly that 40-hex-char value.","If the key was rotated, update the fingerprint in config (or PASSBOLT_GPG_SERVER_KEY_FINGERPRINT env var) to the new key's fingerprint.","Run `passbolt healthcheck` to validate the server key fingerprint/file pairing after fixing config.","Ensure the same key file and fingerprint pair is deployed to all app servers behind the load balancer."],"exampleFix":"// before (config/passbolt.php)\n'serverKey' => ['fingerprint' => '0FC5F0D5B7A4B7F5...', // old fingerprint\n// after\ngpg --show-keys serverkey_private.asc  # read actual fingerprint\n'serverKey' => ['fingerprint' => '<actual-40-char-fingerprint>'],","handlingStrategy":"validation","validationCode":"$fp = strtoupper(str_replace(' ', '', (string)Configure::read('passbolt.gpg.serverKey.fingerprint')));\n$fileFp = trim(shell_exec('gpg --show-keys ' . escapeshellarg($keyPath) . ' 2>/dev/null | awk \\'{print $1}\\' | head -1') ?? '');\nif (strlen($fp) !== 40 || $fp !== $fileFp) {\n    throw new \\RuntimeException('Configured fingerprint does not match key file fingerprint.');\n}","typeGuard":null,"tryCatchPattern":"try {\n    $backend->importServerKeyInKeyring($fingerprint, $keyPath);\n} catch (\\Cake\\Http\\Exception\\InternalErrorException $e) {\n    if (str_contains($e->getMessage(), 'fingerprint does not match')) {\n        // recompute fingerprint from file and update config\n    }\n    throw $e;\n}","preventionTips":["Generate the fingerprint config value from the key file itself, never by hand.","After key rotation, update fingerprint and file together in one change.","Run `passbolt healthcheck` after any server-key change; it checks the pairing."],"tags":["openpgp","server-key","fingerprint-mismatch","config","gnupg"],"backgroundTag":"checksum-mismatch","analyzedSha":"31c1bbc10f32808a607fa9bd81891e898779c0bc","analyzedAt":"2026-09-17T00:04:38.960Z","contentChangedAt":"2026-09-17T00:04:38.960Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}