{"record":{"id":"92a044087f46c9a9","repo":"passbolt/passbolt_api","slug":"could-not-sign-the-text","errorCode":null,"errorMessage":"Could not sign the text. ","messagePattern":"Could not sign the text\\. ","errorType":"exception","errorClass":"Cake\\Core\\Exception\\CakeException","httpStatus":null,"severity":"error","filePath":"src/Utility/OpenPGP/Backends/Gnupg.php","lineNumber":459,"sourceCode":"    /**\n     * Sign a text.\n     *\n     * @param string $text plain text to be signed.\n     * @throws \\Cake\\Core\\Exception\\CakeException if no key was set to sign\n     * @throws \\Cake\\Core\\Exception\\CakeException if there is an issue with the key to sign\n     * @return string signed text\n     */\n    public function sign(string $text): string\n    {\n        $msg = __('Could not sign the text. ');\n        $this->assertSignKey();\n        try {\n            /** @var string|false $signedText */\n            $signedText = $this->_gpg->sign($text);\n            $this->clearSignKeys();\n        } catch (Exception $e) {\n            $this->clearSignKeys();\n            throw new CakeException($msg . ' ' . $e->getMessage(), null, $e);\n        }\n        if ($signedText === false) {\n            throw new CakeException($msg);\n        }\n\n        return $signedText;\n    }\n\n    /**\n     * Removes all keys which were set for decryption before\n     *\n     * @return void\n     */\n    public function clearDecryptKeys(): void\n    {\n        $this->_decryptKeyFingerprint = null;\n        $this->_gpg->cleardecryptkeys();\n    }","sourceCodeStart":441,"sourceCodeEnd":477,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/src/Utility/OpenPGP/Backends/Gnupg.php#L441-L477","documentation":"GnuPG backend failure in Gnupg::sign: the gpg sign call threw or returned false after the sign-key assertion passed, meaning cleartext signing failed at the backend level (e.g. unusable sign key) and a CakeException is raised.","triggerScenarios":"sign($text) where $this->_gpg->sign($text) throws: sign key fingerprint not in keyring, private key passphrase-protected, or gpg-agent cannot access the secret key.","commonSituations":"Server private key re-imported with a passphrase; keyring homedir permissions wrong so gpg-agent can't read the secret key; sign fingerprint config points to a key only present as public; headless environment lacking gpg-agent socket.","solutions":["Check the appended gnupg message for the exact agent/key error","Verify the secret key exists: gpg --list-secret-keys <signFingerprint>","Re-import a passphrase-less private key or ensure the same passphrase setup as when it was added","Fix GNUPGHOME ownership/permissions (700, owned by PHP user) and ensure gpg-agent is running"],"exampleFix":"// before\n$gpg->setSignKey($fingerprintOfPublicOnlyKey);\n$signed = $gpg->sign($text); // CakeException: Could not sign the text. ...\n// after\n$gpg->setSignKey($fingerprintWithSecretKeyInKeyring);\n$signed = $gpg->sign($text);","handlingStrategy":"try-catch","validationCode":"$fp = $gpg->getSignKeyFingerprint();\n$secretKeys = (string) shell_exec(\"gpg --homedir $homedir --list-secret-keys --with-colons $fp\");\nif (!str_contains($secretKeys, 'sec')) {\n    throw new RuntimeException(\"Sign key $fp has no secret key in keyring\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    $signed = $gpg->sign($text);\n} catch (CakeException $e) {\n    $this->log('Signing failed: ' . $e->getMessage());\n    throw new SigningException('Server cannot sign with the configured key.', 0, $e);\n}","preventionTips":["Verify the secret (not just public) key is in the keyring before signing operations","Use passphrase-less server keys or a managed gpg-agent passphrase strategy","Check GNUPGHOME permissions after container/image rebuilds","Add signing smoke tests to healthchecks"],"tags":["openpgp","signing","gnupg","private-key"],"backgroundTag":"openpgp-signing-failed","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"}