ory/hydra · error

invalid elliptic curve key size, use one of 256, 384, or 521

Error message

invalid elliptic curve key size, use one of 256, 384, or 521

What it means

josex.NewEncryptionKey generates ECDH keys for the ECDH_ES / ECDH_ES_A*KW key algorithms on one of three NIST curves selected by the bits parameter: 256 (P-256, also the default when bits == 0), 384 (P-384), or 521 (P-521). Any other non-zero value falls through to this error because elliptic curves cannot be generated at arbitrary sizes.

Source

Thrown at oryx/josex/generate.go:111

		if bits < 2048 {
			return nil, nil, errors.New("invalid key size for RSA key, 2048 or more is required")
		}
		key, err := rsa.GenerateKey(rand.Reader, bits)
		if err != nil {
			return nil, nil, err
		}
		return key.Public(), key, err
	case jose.ECDH_ES, jose.ECDH_ES_A128KW, jose.ECDH_ES_A192KW, jose.ECDH_ES_A256KW:
		var crv elliptic.Curve
		switch bits {
		case 0, 256:
			crv = elliptic.P256()
		case 384:
			crv = elliptic.P384()
		case 521:
			crv = elliptic.P521()
		default:
			return nil, nil, errors.New("invalid elliptic curve key size, use one of 256, 384, or 521")
		}
		key, err := ecdsa.GenerateKey(crv, rand.Reader)
		if err != nil {
			return nil, nil, err
		}
		return key.Public(), key, err
	default:
		return nil, nil, fmt.Errorf("unknown algorithm %s for encryption key", alg)
	}
}

View on GitHub (pinned to 4174065ffb)

Solutions

  1. Use bits = 256, 384, or 521 for ECDH_ES* algorithms (256 is the default; note 521, not 512)
  2. Pass bits = 0 to get the default P-256 key
  3. Do not derive bits from the AES key-wrap name (A128KW still uses a P-256/P-384/P-521 curve, not 128)
  4. Map your security-level setting to the nearest supported curve size before calling

Example fix

// before
pub, priv, err := josex.NewEncryptionKey(jose.ECDH_ES, 512)
// after
pub, priv, err := josex.NewEncryptionKey(jose.ECDH_ES, 521) // P-521
// or default P-256:
pub, priv, err := josex.NewEncryptionKey(jose.ECDH_ES, 0)
Defensive patterns

Strategy: validation

Validate before calling

func validBitsForECDH(bits int) error {
	switch bits {
	case 0, 256, 384, 521:
		return nil
	default:
		return fmt.Errorf("ECDH key size must be 0 (default P-256), 256, 384, or 521 (got %d)", bits)
	}
}

Try / catch

pub, priv, err := josex.NewEncryptionKey(jose.ECDH_ES, bits)
if err != nil {
	if strings.Contains(err.Error(), "use one of 256, 384, or 521") {
		bits = 0 // default P-256
		pub, priv, err = josex.NewEncryptionKey(jose.ECDH_ES, bits)
	}
	if err != nil {
		return fmt.Errorf("generating ECDH encryption key: %w", err)
	}
}

Prevention

When it happens

Trigger: Calling josex.NewEncryptionKey(jose.ECDH_ES, 512) (expecting 512 like ES512), NewEncryptionKey(jose.ECDH_ES_A128KW, 128), NewEncryptionKey(jose.ECDH_ES_A256KW, 528), or any ECDH_* algorithm with bits not in {0, 256, 384, 521}.

Common situations: Assuming the AES key-wrap size (A128KW/A192KW/A256KW: 128/192/256) is the curve size and passing 128 or 192; confusing ES512's 512 with the required 521; a generic 'security level' config (e.g. 192) fed into every key-generation call.

Related errors


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