{"record":{"id":"adb71a6562f3579a","repo":"passbolt/passbolt_api","slug":"the-jwt-private-key-should-be-at-least-0-bytes-long","errorCode":null,"errorMessage":"The JWT private key should be at least {0} bytes long.","messagePattern":"The JWT private key should be at least (.+?) bytes long\\.","errorType":"http","errorClass":"InvalidJwtKeyPairException","httpStatus":500,"severity":"error","filePath":"plugins/PassboltCe/JwtAuthentication/src/Service/AccessToken/JwtKeyPairService.php","lineNumber":127,"sourceCode":"     */\n    public function validateKeyPair(?string $uuid = null): object\n    {\n        // Minimal size of the private key\n        $minSecretKeySize = JwtTokenCreateService::JWT_KEY_LENGTH;\n        $uuid = $uuid ?? UuidFactory::uuid();\n        try {\n            if (!is_readable($this->publicService->getKeyPath())) {\n                throw new Exception(__('The JWT public key could not be read or is not valid.'));\n            }\n            $publicKey = file_get_contents($this->publicService->getKeyPath());\n            $secretKeySize = $this->publicService->getSecretKeySize();\n\n            if ($secretKeySize === 0) {\n                throw new Exception(__('The JWT public key could not be read or is not valid.'));\n            }\n\n            if ($secretKeySize < $minSecretKeySize) {\n                throw new Exception(__(\n                    'The JWT private key should be at least {0} bytes long.',\n                    $this->secretService::JWT_KEY_LENGTH\n                ));\n            }\n\n            $jwt = $this->secretService->createToken($uuid, '2 seconds');\n\n            return JWT::decode($jwt, new Key($publicKey, $this->secretService::JWT_ALG));\n        } catch (Throwable $e) {\n            throw new InvalidJwtKeyPairException($e->getMessage());\n        }\n    }\n\n    /**\n     * @return bool if a key pair exists\n     */\n    public function keyPairExists(): bool\n    {","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltCe/JwtAuthentication/src/Service/AccessToken/JwtKeyPairService.php#L109-L145","documentation":"validateKeyPair() enforces that the JWT private key is at least JWT_KEY_LENGTH (from JwtTokenCreateService, 4096-bit-derived key size) bytes. When getSecretKeySize() is below the minimum, this translated error is thrown with the required length interpolated and wrapped in InvalidJwtKeyPairException.","triggerScenarios":"validateKeyPair() computes $secretKeySize < $minSecretKeySize — i.e. the key pair was generated with a too-small private_key_bits setting or a legacy/weak key was installed manually.","commonSituations":"Old passbolt instances with pre-hardening JWT keys after an upgrade that raised the minimum; hand-generated keys created with default 2048/1024-bit OpenSSL settings; custom $config passed to createKeyPair with low private_key_bits.","solutions":["Regenerate the key pair with adequate size: sudo -u www-data bin/cake passbolt create jwt_keys (service defaults to 4096 bits)","If generating manually, use private_key_bits >= 4096 with OPENSSL_KEYTYPE_RSA in the $config passed to JwtKeyPairService","Confirm JwtTokenCreateService::JWT_KEY_LENGTH to know the exact required byte size in your version","After regenerating, re-run the JWT validation step and have users re-authenticate (tokens signed with the old key are invalid)"],"exampleFix":"// before\n$config = ['private_key_bits' => 2048, 'private_key_type' => OPENSSL_KEYTYPE_RSA];\n// after\n$config = ['private_key_bits' => 4096, 'private_key_type' => OPENSSL_KEYTYPE_RSA];","handlingStrategy":"validation","validationCode":"$size = strlen(file_get_contents($privateKeyPath));\n$min = \\Passbolt\\JwtAuthentication\\Service\\AccessToken\\JwtTokenCreateService::JWT_KEY_LENGTH;\nif ($size < $min) { // regenerate with private_key_bits >= 4096 before validation\n}","typeGuard":null,"tryCatchPattern":"try { $service->validateKeyPair(); } catch (InvalidJwtKeyPairException $e) { // regenerate with 4096-bit RSA and re-validate }","preventionTips":["Always use the service defaults (4096-bit RSA) when generating","Upgrade-time: proactively rotate old short JWT keys","Never hand-install keys smaller than JWT_KEY_LENGTH"],"tags":["jwt","security","key-size","validation"],"backgroundTag":"key-size-below-minimum","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"}