{"record":{"id":"890e5b1bed043fbe","repo":"lcobucci/jwt","slug":"key-provided-is-shorter-than-expectedlength-bits-only-hmac","errorCode":null,"errorMessage":"Key provided is shorter than {expectedLength} bits, only {actualLength} bits provided","messagePattern":"Key provided is shorter than (.+?) bits, only (.+?) bits provided","errorType":"exception","errorClass":"Lcobucci\\JWT\\Signer\\InvalidKeyProvided","httpStatus":null,"severity":"error","filePath":"src/Signer/Hmac.php","lineNumber":20,"sourceCode":"declare(strict_types=1);\n\nnamespace Lcobucci\\JWT\\Signer;\n\nuse Lcobucci\\JWT\\Signer;\n\nuse function hash_equals;\nuse function hash_hmac;\nuse function strlen;\n\nabstract readonly class Hmac implements Signer\n{\n    final public function sign(string $payload, Key $key): string\n    {\n        $actualKeyLength   = 8 * strlen($key->contents());\n        $expectedKeyLength = $this->minimumBitsLengthForKey();\n\n        if ($actualKeyLength < $expectedKeyLength) {\n            throw InvalidKeyProvided::tooShort($expectedKeyLength, $actualKeyLength);\n        }\n\n        return hash_hmac($this->algorithm(), $payload, $key->contents(), true);\n    }\n\n    final public function verify(string $expected, string $payload, Key $key): bool\n    {\n        return hash_equals($expected, $this->sign($payload, $key));\n    }\n\n    /**\n     * @internal\n     *\n     * @return non-empty-string\n     */\n    abstract public function algorithm(): string;\n\n    /**","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/lcobucci/jwt/blob/375813049c24c7111bda8b6884c57b071ceb2fe7/src/Signer/Hmac.php#L2-L38","documentation":"Thrown by Hmac::sign when the key material provided to the Signer is shorter than the minimum bits required by the HMAC algorithm variant (e.g. HS256 requires 128 bits, HS384 192, HS512 256, per RFC 7518). The library enforces this before calling hash_hmac to prevent use of weak keys.","triggerScenarios":"Calling Hmac::sign() (directly or via the JWT Builder) with a Key whose contents are fewer bits than minimumBitsLengthForKey(); also triggered on verify() since it delegates to sign().","commonSituations":"Placeholder secrets like 'secret' in dev config, truncated environment variables, keys loaded from config files with whitespace-only or test values, upgrading from a laxer JWT library that accepted short secrets.","solutions":["Provide a key at least as long as required: HS256 >= 16 bytes, HS384 >= 24 bytes, HS512 >= 32 bytes","Generate a strong secret, e.g. `base64_encode(random_bytes(32))` or `openssl rand -base64 32`","Check the environment variable / config source actually contains the full secret (no truncation or quoting issues)","Align the key length with the algorithm: pick a longer key for HS384/HS512"],"exampleFix":"// before\n$key = InMemory::plainText('secret');\n// after\n$key = InMemory::plainText(base64_encode(random_bytes(32))); // 256 bits","handlingStrategy":"validation","validationCode":"if (strlen($secret) * 8 < 256) { throw new InvalidArgumentException('HMAC key must be >= 256 bits for HS256+' ); }","typeGuard":null,"tryCatchPattern":"try { $builder->signedWith($key); ... } catch (\\Jose\\Component\\Signature\\Exception\\InvalidKeyProvided $e) { /* reject weak key at startup */ }","preventionTips":["Generate secrets with random_bytes(32) or `openssl rand -base64 32`","Validate key strength at application boot, not at first sign","Keep algorithm and key length requirements in one config constant"],"tags":["hmac","jwt","weak-key","security"],"backgroundTag":"missing-credentials","analyzedSha":"375813049c24c7111bda8b6884c57b071ceb2fe7","analyzedAt":"2026-09-14T11:12:28.004Z","contentChangedAt":"2026-09-14T11:12:28.004Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}