dgraph-io/dgraph · error

error parsing ACL key as RSA private key

Error message

error parsing ACL key as RSA private key

What it means

For RS*/PS* JWT algorithms, parseJWTKey expects a PEM-encoded RSA private key and calls jwt.ParseRSAPrivateKeyFromPEM. Any parse failure is wrapped as this error, meaning the provided ACL key is not a valid RSA private key PEM.

Source

Thrown at x/acl_enc_keys.go:114

	return keys, nil
}

func parseJWTKey(alg jwt.SigningMethod, key Sensitive) (interface{}, interface{}, error) {
	switch {
	case strings.HasPrefix(alg.Alg(), "HS"):
		return key, key, nil

	case strings.HasPrefix(alg.Alg(), "ES"):
		pk, err := jwt.ParseECPrivateKeyFromPEM(key)
		if err != nil {
			return nil, nil, errors.Wrapf(err, "error parsing ACL key as ECDSA private key")
		}
		return pk, &pk.PublicKey, nil

	case strings.HasPrefix(alg.Alg(), "RS") || strings.HasPrefix(alg.Alg(), "PS"):
		pk, err := jwt.ParseRSAPrivateKeyFromPEM(key)
		if err != nil {
			return nil, nil, errors.Wrapf(err, "error parsing ACL key as RSA private key")
		}
		return pk, &pk.PublicKey, nil

	case alg.Alg() == "EdDSA":
		pk, err := jwt.ParseEdPrivateKeyFromPEM(key)
		if err != nil {
			return nil, nil, errors.Wrapf(err, "error parsing ACL key as EdDSA private key")
		}
		return pk.(crypto.Signer), pk.(ed25519.PrivateKey).Public(), nil

	default:
		return nil, nil, errors.Errorf("unsupported signing algorithm: %v", alg.Alg())
	}
}

func checkAclKeyLength(alg jwt.SigningMethod, key Sensitive) error {
	if !strings.HasPrefix(alg.Alg(), "HS") {
		return nil

View on GitHub (pinned to 759e242be6)

Solutions

  1. Generate an RSA private key (openssl genrsa -out acl_rsa.pem 2048) and supply that PEM
  2. Or switch jwt-alg to HS256 to use a symmetric secret
  3. Confirm the PEM header is '-----BEGIN RSA PRIVATE KEY-----' or '-----BEGIN PRIVATE KEY-----'
  4. Ensure you are not passing the .pub or certificate file

Example fix

// before
jwt-alg=RS256 with an ECDSA pem file
// after
openssl genrsa -out acl.pem 2048; point hmac-secret-file at acl.pem
Defensive patterns

Strategy: validation

Validate before calling

pemBytes, _ := os.ReadFile(keyPath)
if alg == "RS256" && !strings.Contains(string(pemBytes), "BEGIN") {
    return fmt.Errorf("%s must be a PEM-encoded RSA private key for RS* algs", keyPath)
}
// sanity parse
if _, err := jwt.ParseRSAPrivateKeyFromPEM(pemBytes); err != nil {
    return fmt.Errorf("invalid RSA private key: %w", err)
}

Try / catch

if _, err := x.GetEncAclKeys(flag, encKey); err != nil {
    if strings.Contains(err.Error(), "error parsing ACL key as RSA private key") {
        log.Fatalf("supply a PEM RSA private key (openssl genrsa) for RS*/PS* algs")
    }
    return err
}

Prevention

When it happens

Trigger: Configuring RS256/RS384/RS512/PS* jwt-alg while the ACL key is an HMAC secret, an ECDSA/Ed25519 key, a certificate, or non-PEM bytes.

Common situations: Pointing the key at a certificate (.crt) or public key instead of the private key; PKCS#1 vs PKCS#8 confusion (usually both parse); copying a shared secret from a previous HS setup.

Related errors


AI-assisted analysis of dgraph-io/dgraph@759e242be6 (2026-09-01). Data as JSON: /api/errors/f90dd136c72b8a65. Report an issue: GitHub.