{"record":{"id":"46a756d42c81d6e3","repo":"passbolt/passbolt_api","slug":"the-openpgp-key-can-not-be-used-to-encrypt-46a756","errorCode":null,"errorMessage":"The OpenPGP key can not be used to encrypt.","messagePattern":"The OpenPGP key can not be used to encrypt\\.","errorType":"validation","errorClass":"CustomValidationException","httpStatus":400,"severity":"error","filePath":"src/Service/Setup/SetupCompleteService.php","lineNumber":97,"sourceCode":"        PublicKeyValidationService::parseAndValidatePublicKey(\n            $gpgkey->armored_key,\n            PublicKeyValidationService::getStrictRules()\n        );\n\n        // Check business rules before saving\n        $this->Gpgkeys->checkRules($gpgkey);\n        if ($gpgkey->getErrors()) {\n            throw new ValidationException(__('The OpenPGP key data is not valid.'), $gpgkey, $this->Gpgkeys);\n        }\n\n        // Check key can be used to encrypt\n        // This can happen for example if the key is created in the future\n        // or some other issue prevent the backend to use it, we don't want to fail at the login step\n        if (Configure::read('passbolt.gpg.experimental.encryptValidate')) {\n            if (!PublicKeyCanEncryptCheckService::check($gpgkey->armored_key, $gpgkey->fingerprint)) {\n                $msg = __('The OpenPGP key can not be used to encrypt.');\n                Log::debug($msg, [$gpgkey->armored_key]);\n                throw new CustomValidationException($msg, ['gpgkey' => ['armored_key' => $msg]]);\n            }\n        }\n\n        // Consume atomically before the user save so a losing concurrent request never reaches persistence.\n        $this->consumeTokenOrFail($token);\n\n        $user->active = true;\n        $user->gpgkey = $gpgkey;\n\n        return $user;\n    }\n\n    /**\n     * Saves and performs some checks on the user and its association\n     *\n     * @param \\App\\Model\\Entity\\User $user User to save\n     * @param array|null $saveOptions options\n     * @return \\App\\Model\\Entity\\User","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/src/Service/Setup/SetupCompleteService.php#L79-L115","documentation":"When the experimental config passbolt.gpg.experimental.encryptValidate is enabled, the server tries to actually encrypt to the submitted public key; if the encryption check fails a CustomValidationException is thrown. This guards against keys the backend GnuPG cannot use, which would otherwise only surface as login failures later.","triggerScenarios":"Setup complete call with passbolt.gpg.experimental.encryptValidate=true and a key GnuPG cannot encrypt to: key creation date in the future, unsupported/weak algorithm, corrupted key packet, or fingerprint mismatch.","commonSituations":"Server clock skew making imported keys appear created in the future; keys generated with algorithms disabled in the server's GnuPG/gnupg homedir; old system keys after GnuPG upgrade.","solutions":["Verify the key's creation date is not in the future (fix server clock or regenerate the key)","Regenerate the key with a GnuPG-supported algorithm (e.g. RSA-3072/4096 or modern ECC) and retry","Test locally that GnuPG can encrypt to the key: gpg --import key.asc && echo test | gpg --encrypt -r <fingerprint>","Set Configure::read('passbolt.gpg.experimental.encryptValidate') to false in config to skip this experimental check (with the known trade-off)"],"exampleFix":"// config/passbolt.php\n// before\n'gpg' => ['experimental' => ['encryptValidate' => true]],\n// after (only if accepting the risk of unusable keys)\n'gpg' => ['experimental' => ['encryptValidate' => false]],","handlingStrategy":"validation","validationCode":"// pre-check the key can encrypt (same check the server runs)\nuse App\\Service\\OpenPGP\\PublicKeyCanEncryptCheckService;\n$ok = PublicKeyCanEncryptCheckService::check($armoredKey, $fingerprint);","typeGuard":null,"tryCatchPattern":"try {\n    $user = $setupCompleteService->complete($userId);\n} catch (\\App\\Error\\Exception\\CustomValidationException $e) {\n    $msg = $e->getErrors()['gpgkey']['armored_key'] ?? $e->getMessage();\n}","preventionTips":["Keep server clock synchronized (NTP) so future-dated keys are detected","Avoid exotic/deprecated key algorithms not supported by server GnuPG","Verify with `gpg --encrypt -r <fingerprint>` locally before submission","Know that encryptValidate is experimental; treat its failures as key-quality signals"],"tags":["openpgp","gnupg","encryption","setup"],"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"}