{"record":{"id":"05abf120411dcdfd","repo":"passbolt/passbolt_api","slug":"can-not-sign-without-a-key-set-a-sign-key-first","errorCode":null,"errorMessage":"Can not sign without a key. Set a sign key first.","messagePattern":"Can not sign without a key\\. Set a sign key first\\.","errorType":"exception","errorClass":"Cake\\Core\\Exception\\CakeException","httpStatus":null,"severity":"error","filePath":"src/Utility/OpenPGP/Traits/OpenPGPCommonAssertsTrait.php","lineNumber":68,"sourceCode":"     * @return void\n     */\n    public function assertKeyInKeyring(string $fingerprint): void\n    {\n        if (!$this->isKeyInKeyring($fingerprint)) {\n            throw new CakeException(__('The key {0} was not found in the keyring', $fingerprint));\n        }\n    }\n\n    /**\n     * Assert the signature key is set\n     *\n     * @throws \\Cake\\Core\\Exception\\CakeException if not signature key is set\n     * @return void\n     */\n    public function assertSignKey(): void\n    {\n        if (empty($this->_signKeyFingerprint)) {\n            throw new CakeException('Can not sign without a key. Set a sign key first.');\n        }\n    }\n\n    /**\n     * Assert the verification key is set\n     *\n     * @throws \\Cake\\Core\\Exception\\CakeException if not signature key is set\n     * @return void\n     */\n    public function assertVerifyKey(): void\n    {\n        if (empty($this->_verifyKeyFingerprint)) {\n            throw new CakeException('Can not verify without a key. Set a verification key first.');\n        }\n    }\n\n    /**\n     * Check if an encryption key is set","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/src/Utility/OpenPGP/Traits/OpenPGPCommonAssertsTrait.php#L50-L86","documentation":"assertSignKey() is a precondition check for OpenPGP signing operations in OpenPGPCommonAssertsTrait. It throws a CakeException when the private property _signKeyFingerprint is empty, because GnuPG cannot create a signature without a sign key having been set via setSignKey().","triggerScenarios":"Calling sign() (or any operation that internally calls assertSignKey) on an OpenPGP utility instance where setSignKey() was never called, or was called with an empty/invalid fingerprint so _signKeyFingerprint stayed empty.","commonSituations":"Forgotten setSignKey() call before signing emails or payloads; signing code executed in a context (CLI task, test) where the key setup bootstrap didn't run; refactors that moved signing into a new service without carrying the key configuration over.","solutions":["Call setSignKey() with a valid secret-key fingerprint before signing.","Ensure the sign key fingerprint is configured in application settings and loaded into the OpenPGP utility during bootstrap.","Confirm the fingerprint actually set is non-empty (log/inspect the value passed to setSignKey)."],"exampleFix":"// before\n$signed = $gpg->sign($text); // throws: no sign key\n// after\n$gpg->setSignKey($signKeyFingerprint, $passphrase);\n$signed = $gpg->sign($text);","handlingStrategy":"type-guard","validationCode":"if (empty($gpg->getSignKeyFingerprint())) {\n    $gpg->setSignKey($configSignKeyFingerprint, $passphrase);\n}","typeGuard":"function canSign($gpg): bool {\n    return isset($gpg) && !empty($gpg->getSignKeyFingerprint());\n}","tryCatchPattern":"try {\n    $signed = $gpg->sign($text);\n} catch (\\Cake\\Core\\Exception\\CakeException $e) {\n    if (str_contains($e->getMessage(), 'sign without a key')) {\n        $gpg->setSignKey($fingerprint, $passphrase);\n        $signed = $gpg->sign($text);\n    } else { throw $e; }\n}","preventionTips":["Centralize OpenPGP key setup in a single factory/bootstrap so sign key is always set.","Never construct signing-capable instances ad hoc in commands or tests without the shared factory.","Assert key setup in unit tests before exercising sign paths."],"tags":["openpgp","signing","missing-key"],"backgroundTag":"empty-required-field","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"}