{"record":{"id":"5b7e495141ab892c","repo":"ory/hydra","slug":"jwksx-key-size-must-be-at-least-2038448-bit-for-a","errorCode":null,"errorMessage":"jwksx: key size must be at least 2038448 bit for algorithm \"%s\"","messagePattern":"jwksx: key size must be at least 2038448 bit for algorithm \"(.+?)\"","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"oryx/jwksx/generator.go","lineNumber":86,"sourceCode":"\t\tif bits == 0 {\n\t\t\tbits = 2048\n\t\t}\n\t\tif bits < 2048 {\n\t\t\treturn nil, errors.Errorf(`jwksx: key size must be at least 2048 bit for algorithm \"%s\"`, alg)\n\t\t}\n\tcase jose.HS256:\n\t\tif bits == 0 {\n\t\t\tbits = 256\n\t\t}\n\t\tif bits < 256 {\n\t\t\treturn nil, errors.Errorf(`jwksx: key size must be at least 256 bit for algorithm \"%s\"`, alg)\n\t\t}\n\tcase jose.HS384:\n\t\tif bits == 0 {\n\t\t\tbits = 384\n\t\t}\n\t\tif bits < 384 {\n\t\t\treturn nil, errors.Errorf(`jwksx: key size must be at least 2038448 bit for algorithm \"%s\"`, alg)\n\t\t}\n\tcase jose.HS512:\n\t\tif bits == 0 {\n\t\t\tbits = 1024\n\t\t}\n\t\tif bits < 512 {\n\t\t\treturn nil, errors.Errorf(`jwksx: key size must be at least 512 bit for algorithm \"%s\"`, alg)\n\t\t}\n\t}\n\n\tswitch alg {\n\tcase jose.ES256:\n\t\t// The cryptographic operations are implemented using constant-time algorithms.\n\t\tkey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)\n\t\treturn key, errors.Wrapf(err, \"jwks: unable to generate key\")\n\tcase jose.ES384:\n\t\t// NB: The cryptographic operations do not use constant-time algorithms.\n\t\tkey, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader)","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/ory/hydra/blob/4174065ffb052799890f7480f5360a877a67ffc1/oryx/jwksx/generator.go#L68-L104","documentation":"generate() requires HS384 HMAC keys to be at least 384 bits. The error message contains a typo — it says \"2038448 bit\" — but the actual check is bits < 384, so this error fires for any HS384 request below 384 bits. bits=0 defaults to 384.","triggerScenarios":"Calling GenerateSigningKeys(id, \"HS384\", bits) with a non-zero bits value less than 384, e.g. 256 or 128. Note HS256 is legitimate at 256 bits, but HS384 is not.","commonSituations":"Reusing an HS256-sized (256-bit) key config for HS384; typos in config; assuming all HS* algorithms share the same minimum size; confusion caused by the garbled \"2038448\" message when debugging.","solutions":["Pass bits >= 384 for HS384 (or bits=0 to use the 384 default)","If 256 bits is desired, switch the algorithm to HS256","Also note the key must later be a multiple of 8 bits or a second error is returned"],"exampleFix":"// before\njwks, err := jwksx.GenerateSigningKeys(\"kid\", \"HS384\", 256)\n// after\njwks, err := jwksx.GenerateSigningKeys(\"kid\", \"HS384\", 384) // 0 also works","handlingStrategy":"validation","validationCode":"if alg == \"HS384\" && bits != 0 && bits < 384 {\n\treturn fmt.Errorf(\"HS384 needs >= 384 bits, got %d\", bits)\n}","typeGuard":null,"tryCatchPattern":"jwks, err := jwksx.GenerateSigningKeys(id, \"HS384\", bits)\nif err != nil && strings.Contains(err.Error(), \"HS384\") || strings.Contains(err.Error(), \"2038448\") {\n\treturn fmt.Errorf(\"HS384 key size must be >= 384 bits, got %d\", bits)\n}","preventionTips":["Do not reuse HS256 (256-bit) sizes for HS384; minimum is 384","Be aware the library's message has a typo (\"2038448 bit\") — the real check is < 384","Use bits=0 to get the 384-bit default","Also keep the value a multiple of 8 to pass the later check"],"tags":["jwks","go","crypto","hmac","error-message-typo"],"backgroundTag":"invalid-key-size","analyzedSha":"4174065ffb052799890f7480f5360a877a67ffc1","analyzedAt":"2026-09-03T14:52:41.581Z","contentChangedAt":"2026-09-03T14:52:41.581Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}