{"record":{"id":"727599b000a29ad7","repo":"dgraph-io/dgraph","slug":"error-parsing-acl-key-as-eddsa-private-key","errorCode":null,"errorMessage":"error parsing ACL key as EdDSA private key","messagePattern":"error parsing ACL key as EdDSA private key","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"x/acl_enc_keys.go","lineNumber":121,"sourceCode":"\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\n\t}\n\n\tsl, err := strconv.Atoi(strings.TrimPrefix(alg.Alg(), \"HS\"))\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"error finding sha length for algo %v\", alg.Alg())\n\t}\n","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/dgraph-io/dgraph/blob/759e242be62c91f8d084da06ad0c8d21256d9c07/x/acl_enc_keys.go#L103-L139","documentation":"For the EdDSA algorithm, parseJWTKey calls jwt.ParseEdPrivateKeyFromPEM, which requires a PEM-encoded Ed25519 private key. Failure to parse is wrapped in this error; a successful parse also requires the key to be castable to ed25519.PrivateKey.","triggerScenarios":"Setting jwt-alg=EdDSA while the ACL key is not an Ed25519 private key PEM (e.g. RSA, ECDSA, HMAC secret, or raw 32 bytes without PEM encoding).","commonSituations":"Generating an ed25519 key with a tool that outputs raw or OpenSSH-format keys not accepted as PKCS#8 PEM; reusing a key from a different algorithm configuration.","solutions":["Generate an Ed25519 private key as PKCS#8 PEM (openssl genpkey -algorithm ed25519 -out acl_ed.pem)","Or change jwt-alg to HS256/RS256 to match the key you already have","Ensure the key file contains full PEM blocks, not raw key bytes","Confirm the vendored golang-jwt version supports EdDSA parsing"],"exampleFix":"// before\necho -n \"raw32byteskey...\" > acl.key; jwt-alg=EdDSA\n// after\nopenssl genpkey -algorithm ed25519 -out acl.pem; jwt-alg=EdDSA with hmac-secret-file=/path/acl.pem","handlingStrategy":"validation","validationCode":"pemBytes, _ := os.ReadFile(keyPath)\nif alg == \"EdDSA\" {\n    if _, err := jwt.ParseEdPrivateKeyFromPEM(pemBytes); err != nil {\n        return fmt.Errorf(\"need PKCS#8 Ed25519 private key PEM: %w\", err)\n    }\n}","typeGuard":null,"tryCatchPattern":"if _, err := x.GetEncAclKeys(flag, encKey); err != nil {\n    if strings.Contains(err.Error(), \"error parsing ACL key as EdDSA private key\") {\n        log.Fatalf(\"generate with: openssl genpkey -algorithm ed25519\")\n    }\n    return err\n}","preventionTips":["Generate Ed25519 keys as PKCS#8 PEM only; avoid raw or OpenSSH-format keys","Confirm the jwt library version supports EdDSA","Align jwt-alg with the actual key type in your config"],"tags":["jwt","acl","crypto","ed25519"],"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"}