Tencent/WeKnora · error

empty JWK modulus or exponent

Error message

empty JWK modulus or exponent

What it means

When converting a JWK (n = modulus, e = exponent) into an rsa.PublicKey, either field decoded to zero bytes. An RSA key cannot be built without both, so the function rejects the JWK. This indicates the JWKS entry is malformed or is not an actual RSA key.

Source

Thrown at internal/application/service/user.go:1857

		return b, nil
	}
	return base64.URLEncoding.DecodeString(value)
}

func (k oidcJWK) rsaPublicKey() (*rsa.PublicKey, error) {
	if !strings.EqualFold(k.Kty, "RSA") {
		return nil, fmt.Errorf("unsupported JWK key type: %s", k.Kty)
	}
	nBytes, err := decodeJWKBase64(k.N)
	if err != nil {
		return nil, fmt.Errorf("invalid JWK modulus: %w", err)
	}
	eBytes, err := decodeJWKBase64(k.E)
	if err != nil {
		return nil, fmt.Errorf("invalid JWK exponent: %w", err)
	}
	if len(nBytes) == 0 || len(eBytes) == 0 {
		return nil, errors.New("empty JWK modulus or exponent")
	}
	eInt := new(big.Int).SetBytes(eBytes)
	if !eInt.IsInt64() {
		return nil, errors.New("invalid JWK exponent value")
	}
	e := int(eInt.Int64())
	if e <= 0 {
		return nil, errors.New("invalid JWK exponent value")
	}
	return &rsa.PublicKey{N: new(big.Int).SetBytes(nBytes), E: e}, nil
}

func (jwks *oidcJWKS) rsaKeyForKid(kid string) (*rsa.PublicKey, error) {
	var usable []oidcJWK
	for _, k := range jwks.Keys {
		if k.Use != "" && !strings.EqualFold(k.Use, "sig") {
			continue
		}

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Inspect the JWKS document and confirm the matching key has non-empty 'n' and 'e' fields.
  2. Filter JWKS entries by kty == "RSA" before parsing.
  3. Refresh the JWKS from the authoritative jwks_uri in case a cached copy is corrupt.
  4. Report/fix the provider if it publishes incomplete RSA keys.

Example fix

// before: parsing every key in JWKS
for _, k := range jwks.Keys { buildRSAKey(k) }
// after: only RSA keys
for _, k := range jwks.Keys {
  if k.Kty == "RSA" && k.N != "" && k.E != "" { buildRSAKey(k) }
}
Defensive patterns

Strategy: validation

Validate before calling

func validRSAJWK(k jwk) bool {
    n, errN := base64.RawURLEncoding.DecodeString(k.N)
    e, errE := base64.RawURLEncoding.DecodeString(k.E)
    return k.Kty == "RSA" && errN == nil && errE == nil && len(n) > 0 && len(e) > 0
}

Type guard

func isRSAJWK(k jwk) bool { return k.Kty == "RSA" && k.N != "" && k.E != "" }

Prevention

When it happens

Trigger: decodeJWKBase64 on k.N or k.E yields empty output — e.g. the JWKS key object is missing the 'n' or 'e' field, or they are empty strings.

Common situations: Provider publishes non-RSA keys (EC, OKP) in the same JWKS with missing n/e; truncated or hand-edited JWKS documents; a key entry that is only a partial stub.

Related errors


AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02). Data as JSON: /api/errors/790a6228547d8bcd. Report an issue: GitHub.