passbolt/passbolt_api · error · InvalidJwtKeyPairException

The JWT private key should be at least

Error message

The JWT private key should be at least {0} bytes long.

What it means

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.

Solutions

  1. Regenerate the key pair with adequate size: sudo -u www-data bin/cake passbolt create jwt_keys (service defaults to 4096 bits)
  2. If generating manually, use private_key_bits >= 4096 with OPENSSL_KEYTYPE_RSA in the $config passed to JwtKeyPairService
  3. Confirm JwtTokenCreateService::JWT_KEY_LENGTH to know the exact required byte size in your version
  4. After regenerating, re-run the JWT validation step and have users re-authenticate (tokens signed with the old key are invalid)

Example fix

// before
$config = ['private_key_bits' => 2048, 'private_key_type' => OPENSSL_KEYTYPE_RSA];
// after
$config = ['private_key_bits' => 4096, 'private_key_type' => OPENSSL_KEYTYPE_RSA];
Defensive patterns

Strategy: validation

Validate before calling

$size = strlen(file_get_contents($privateKeyPath));
$min = \Passbolt\JwtAuthentication\Service\AccessToken\JwtTokenCreateService::JWT_KEY_LENGTH;
if ($size < $min) { // regenerate with private_key_bits >= 4096 before validation
}

Try / catch

try { $service->validateKeyPair(); } catch (InvalidJwtKeyPairException $e) { // regenerate with 4096-bit RSA and re-validate }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17). Data as JSON: /api/errors/adb71a6562f3579a. Report an issue: GitHub.

Appendix: source

Thrown at plugins/PassboltCe/JwtAuthentication/src/Service/AccessToken/JwtKeyPairService.php:127

     */
    public function validateKeyPair(?string $uuid = null): object
    {
        // Minimal size of the private key
        $minSecretKeySize = JwtTokenCreateService::JWT_KEY_LENGTH;
        $uuid = $uuid ?? UuidFactory::uuid();
        try {
            if (!is_readable($this->publicService->getKeyPath())) {
                throw new Exception(__('The JWT public key could not be read or is not valid.'));
            }
            $publicKey = file_get_contents($this->publicService->getKeyPath());
            $secretKeySize = $this->publicService->getSecretKeySize();

            if ($secretKeySize === 0) {
                throw new Exception(__('The JWT public key could not be read or is not valid.'));
            }

            if ($secretKeySize < $minSecretKeySize) {
                throw new Exception(__(
                    'The JWT private key should be at least {0} bytes long.',
                    $this->secretService::JWT_KEY_LENGTH
                ));
            }

            $jwt = $this->secretService->createToken($uuid, '2 seconds');

            return JWT::decode($jwt, new Key($publicKey, $this->secretService::JWT_ALG));
        } catch (Throwable $e) {
            throw new InvalidJwtKeyPairException($e->getMessage());
        }
    }

    /**
     * @return bool if a key pair exists
     */
    public function keyPairExists(): bool
    {

View on GitHub (pinned to 31c1bbc10f)