{"record":{"id":"af8c845acdddcff3","repo":"passbolt/passbolt_api","slug":"could-not-import-the-user-openpgp-key-gpgauthenticator","errorCode":null,"errorMessage":"Could not import the user OpenPGP key.","messagePattern":"Could not import the user OpenPGP key\\.","errorType":"http","errorClass":"InternalErrorException","httpStatus":500,"severity":"error","filePath":"src/Authenticator/GpgAuthenticator.php","lineNumber":372,"sourceCode":"    /**\n     * Set user key for encryption and import it in the keyring if needed\n     *\n     * @param string $fingerprint fingerprint\n     * @throws \\Cake\\Http\\Exception\\InternalErrorException when the key is not valid\n     * @return void\n     */\n    private function _initUserKey(string $fingerprint): void\n    {\n        try {\n            $this->_gpg->setEncryptKeyFromFingerprint($fingerprint);\n        } catch (Exception $exception) {\n            // Try to import the key in keyring again\n            try {\n                $this->_gpg->importKeyIntoKeyring($this->_user->gpgkey->armored_key);\n                $this->_gpg->setEncryptKeyFromFingerprint($fingerprint);\n            } catch (Exception $exception) {\n                $msg = __('Could not import the user OpenPGP key.');\n                throw new InternalErrorException($msg, 500, $exception);\n            }\n        }\n    }\n\n    /**\n     * Find a user record from a public key fingerprint\n     *\n     * @return \\App\\Model\\Entity\\User|null\n     */\n    private function _identifyUserWithFingerprint(): ?User\n    {\n        // First we check if we can get the user with the key fingerprint\n        if (!isset($this->_data['keyid']) || !is_string($this->_data['keyid'])) {\n            $this->_debug('No key id set.');\n\n            return null;\n        }\n","sourceCodeStart":354,"sourceCodeEnd":390,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/src/Authenticator/GpgAuthenticator.php#L354-L390","documentation":"Thrown by GpgAuthenticator::_initUserKey() when the client's OpenPGP public key cannot be loaded into the server keyring for encryption. setEncryptKeyFromFingerprint() failed, and the fallback re-import of the user's armored key from the database (user.gpgkey.armored_key) also failed. Reported as InternalErrorException (HTTP 500) with the underlying exception attached.","triggerScenarios":"During GPGAuth stage1, when encrypting the server verify token to the user's key fails because the key is not in the keyring, and importKeyIntoKeyring($this->_user->gpgkey->armored_key) throws (malformed armored key, revoked/expired key material stored in DB, gnupg import error).","commonSituations":"User registered with a corrupted or non-armored key blob in the gpgkeys table; key revoked or with unusable subkeys after a version change; GnuPG keyring on the server full/broken or homedir permissions wrong so imports silently fail; old keys imported under a different homedir after server migration.","solutions":["Inspect the wrapped exception to see the gnupg import/encrypt failure reason.","Ask the user to re-upload/re-register a valid, unrevoked OpenPGP key; verify the armored_key column contains a full '-----BEGIN PGP PUBLIC KEY BLOCK-----' blob.","Check server GnuPG health: writable homedir, sufficient keyring permissions, gpg binary working (gpg --version); clear stale keyring entries for that fingerprint and retry.","If the key is revoked/expired in the DB, remove it and let the user re-register or update the key via the profile UI."],"exampleFix":"// before: trusting whatever armored key is stored\n$this->_gpg->importKeyIntoKeyring($this->_user->gpgkey->armored_key);\n\n// after: validate the armored key before import\nif (!PublicKeyValidationService::isValidArmoredKey($this->_user->gpgkey->armored_key)) {\n    throw new BadRequestException(__('The user OpenPGP key is invalid.'));\n}\n$this->_gpg->importKeyIntoKeyring($this->_user->gpgkey->armored_key);","handlingStrategy":"try-catch","validationCode":"if (!PublicKeyValidationService::isValidArmoredKey($user->gpgkey->armored_key)) {\n    // reject at registration/upload time, before auth needs to encrypt to it\n}","typeGuard":"function hasUsableArmoredKey(?User $user): bool {\n    return $user !== null\n        && $user->gpgkey !== null\n        && is_string($user->gpgkey->armored_key)\n        && str_contains($user->gpgkey->armored_key, 'BEGIN PGP PUBLIC KEY BLOCK');\n}","tryCatchPattern":"try {\n    $gpg->importKeyIntoKeyring($armoredKey);\n    $gpg->setEncryptKeyFromFingerprint($fingerprint);\n} catch (Exception $e) {\n    // surface 500, log $e, prompt user to re-upload a valid key\n}","preventionTips":["Validate armored keys at registration and profile-update time with PublicKeyValidationService.","Reject revoked/expired keys on upload so unusable keys never reach auth.","After server migrations, warm the keyring or rely on import fallback; keep GNUPGHOME persistent.","Alert on repeated import failures per user (indicates bad key data in DB)."],"tags":["gnupg","user-key","keyring","key-import","authentication"],"backgroundTag":"invalid-config-value","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"}