{"record":{"id":"f90dd136c72b8a65","repo":"dgraph-io/dgraph","slug":"error-parsing-acl-key-as-rsa-private-key","errorCode":null,"errorMessage":"error parsing ACL key as RSA private key","messagePattern":"error parsing ACL key as RSA private key","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"x/acl_enc_keys.go","lineNumber":114,"sourceCode":"\treturn keys, nil\n}\n\nfunc parseJWTKey(alg jwt.SigningMethod, key Sensitive) (interface{}, interface{}, error) {\n\tswitch {\n\tcase strings.HasPrefix(alg.Alg(), \"HS\"):\n\t\treturn key, key, nil\n\n\tcase strings.HasPrefix(alg.Alg(), \"ES\"):\n\t\tpk, err := jwt.ParseECPrivateKeyFromPEM(key)\n\t\tif err != nil {\n\t\t\treturn nil, nil, errors.Wrapf(err, \"error parsing ACL key as ECDSA private key\")\n\t\t}\n\t\treturn pk, &pk.PublicKey, nil\n\n\tcase strings.HasPrefix(alg.Alg(), \"RS\") || strings.HasPrefix(alg.Alg(), \"PS\"):\n\t\tpk, err := jwt.ParseRSAPrivateKeyFromPEM(key)\n\t\tif err != nil {\n\t\t\treturn nil, nil, errors.Wrapf(err, \"error parsing ACL key as RSA private key\")\n\t\t}\n\t\treturn pk, &pk.PublicKey, nil\n\n\tcase alg.Alg() == \"EdDSA\":\n\t\tpk, err := jwt.ParseEdPrivateKeyFromPEM(key)\n\t\tif err != nil {\n\t\t\treturn nil, nil, errors.Wrapf(err, \"error parsing ACL key as EdDSA private key\")\n\t\t}\n\t\treturn pk.(crypto.Signer), pk.(ed25519.PrivateKey).Public(), nil\n\n\tdefault:\n\t\treturn nil, nil, errors.Errorf(\"unsupported signing algorithm: %v\", alg.Alg())\n\t}\n}\n\nfunc checkAclKeyLength(alg jwt.SigningMethod, key Sensitive) error {\n\tif !strings.HasPrefix(alg.Alg(), \"HS\") {\n\t\treturn nil","sourceCodeStart":96,"sourceCodeEnd":132,"githubUrl":"https://github.com/dgraph-io/dgraph/blob/759e242be62c91f8d084da06ad0c8d21256d9c07/x/acl_enc_keys.go#L96-L132","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Generate an RSA private key (openssl genrsa -out acl_rsa.pem 2048) and supply that PEM","Or switch jwt-alg to HS256 to use a symmetric secret","Confirm the PEM header is '-----BEGIN RSA PRIVATE KEY-----' or '-----BEGIN PRIVATE KEY-----'","Ensure you are not passing the .pub or certificate file"],"exampleFix":"// before\njwt-alg=RS256 with an ECDSA pem file\n// after\nopenssl genrsa -out acl.pem 2048; point hmac-secret-file at acl.pem","handlingStrategy":"validation","validationCode":"pemBytes, _ := os.ReadFile(keyPath)\nif alg == \"RS256\" && !strings.Contains(string(pemBytes), \"BEGIN\") {\n    return fmt.Errorf(\"%s must be a PEM-encoded RSA private key for RS* algs\", keyPath)\n}\n// sanity parse\nif _, err := jwt.ParseRSAPrivateKeyFromPEM(pemBytes); err != nil {\n    return fmt.Errorf(\"invalid RSA private key: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"if _, err := x.GetEncAclKeys(flag, encKey); err != nil {\n    if strings.Contains(err.Error(), \"error parsing ACL key as RSA private key\") {\n        log.Fatalf(\"supply a PEM RSA private key (openssl genrsa) for RS*/PS* algs\")\n    }\n    return err\n}","preventionTips":["Generate with openssl genrsa and pass the private key PEM","Do not substitute certificates or .pub files","Keep key generation in a documented runbook step"],"tags":["jwt","acl","crypto","rsa"],"backgroundTag":"jwt-key-format-mismatch","analyzedSha":"759e242be62c91f8d084da06ad0c8d21256d9c07","analyzedAt":"2026-09-01T14:42:12.034Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}