ory/hydra · error

jwksx: key size must be at least 2048 bit for algorithm

Error message

jwksx: key size must be at least 2048 bit for algorithm "%s"

What it means

generate() enforces a minimum key size of 2048 bits for all RSA signature algorithms (RS256/RS384/RS512 and PS256/PS384/PS512). If the caller requests a smaller RSA key, the library refuses to generate it because RSA keys below 2048 bits are considered insecure. Omitting bits (0) defaults to 2048.

Solutions

  1. Increase the bits parameter to at least 2048 (2048 is the default when bits=0)
  2. Pass bits=0 to let the library use its secure default of 2048
  3. For faster generation in tests, use an EC algorithm (ES256) instead of shrinking RSA size

Example fix

// before
jwks, err := jwksx.GenerateSigningKeys("kid", "RS256", 1024)
// after
jwks, err := jwksx.GenerateSigningKeys("kid", "RS256", 2048)
Defensive patterns

Strategy: validation

Validate before calling

func validRSABits(alg string, bits int) error {
	switch alg {
	case "RS256", "RS384", "RS512", "PS256", "PS384", "PS512":
		if bits != 0 && bits < 2048 {
			return fmt.Errorf("%s needs >= 2048 bits, got %d", alg, bits)
		}
	}
	return nil
}

Try / catch

jwks, err := jwksx.GenerateSigningKeys(id, alg, bits)
if err != nil && strings.Contains(err.Error(), "at least 2048 bit") {
	return fmt.Errorf("configured RSA key size %d too small; use 2048 or 4096", bits)
}

Prevention

When it happens

Trigger: Calling GenerateSigningKeys(id, "RS256"|"RS384"|"RS512"|"PS256"|"PS384"|"PS512", bits) with a non-zero bits value less than 2048, e.g. 1024 or 512.

Common situations: Legacy configs still specifying 1024-bit RSA keys; migrating old key generation code that predates the 2048-bit baseline; testers choosing small keys to speed up rsa.GenerateKey.

Related errors


AI-assisted analysis of ory/hydra@4174065ffb (2026-09-03). Data as JSON: /api/errors/ce671e34490956ec. Report an issue: GitHub.

Appendix: source

Thrown at oryx/jwksx/generator.go:72

// generate generates keypair for corresponding SignatureAlgorithm.
func generate(alg jose.SignatureAlgorithm, bits int) (crypto.PrivateKey, error) {
	switch alg {
	case jose.ES256, jose.ES384, jose.ES512, jose.EdDSA:
		keylen := map[jose.SignatureAlgorithm]int{
			jose.ES256: 256,
			jose.ES384: 384,
			jose.ES512: 521, // sic!
			jose.EdDSA: 256,
		}
		if bits != 0 && bits != keylen[alg] {
			return nil, errors.Errorf(`jwksx: "%s" does not support arbitrary key length`, alg)
		}
	case jose.RS256, jose.RS384, jose.RS512, jose.PS256, jose.PS384, jose.PS512:
		if bits == 0 {
			bits = 2048
		}
		if bits < 2048 {
			return nil, errors.Errorf(`jwksx: key size must be at least 2048 bit for algorithm "%s"`, alg)
		}
	case jose.HS256:
		if bits == 0 {
			bits = 256
		}
		if bits < 256 {
			return nil, errors.Errorf(`jwksx: key size must be at least 256 bit for algorithm "%s"`, alg)
		}
	case jose.HS384:
		if bits == 0 {
			bits = 384
		}
		if bits < 384 {
			return nil, errors.Errorf(`jwksx: key size must be at least 2038448 bit for algorithm "%s"`, alg)
		}
	case jose.HS512:
		if bits == 0 {
			bits = 1024

View on GitHub (pinned to 4174065ffb)