shadowsocks/shadowsocks-rust · error

`users[].password` should be base64 encoded

Error message

`users[].password` should be base64 encoded

What it means

Thrown when an EIP (extensible identity providers) entry under `users` in a server config has a `password` field that `ServerUser::with_encoded_key` cannot decode. For AEAD-2022 and multi-user setups, each user's key must be a base64-encoded key of the exact length the cipher requires; any non-base64 or wrong-length string fails with ErrorKind::Malformed.

Source

Thrown at crates/shadowsocks-service/src/config.rs:2308

                        let err = Error::new(
                            ErrorKind::Malformed,
                            "server config create failed",
                            Some(format!("{}", serr)),
                        );
                        return Err(err);
                    }
                };
                nsvr.set_source(server_source);

                // Extensible Identity Header, Users
                if let Some(users) = svr.users {
                    let mut user_manager = ServerUserManager::new();

                    for user in users {
                        let user = match ServerUser::with_encoded_key(user.name, &user.password) {
                            Ok(u) => u,
                            Err(..) => {
                                let err = Error::new(
                                    ErrorKind::Malformed,
                                    "`users[].password` should be base64 encoded",
                                    None,
                                );
                                return Err(err);
                            }
                        };

                        user_manager.add_user(user);
                    }

                    nsvr.set_user_manager(user_manager);
                }

                match svr.mode {
                    Some(mode) => match mode.parse::<Mode>() {
                        Ok(mode) => nsvr.set_mode(mode),
                        Err(..) => {

View on GitHub (pinned to 8eb0f0a65b)

Solutions

  1. Generate the user key with `openssl rand -base64 32` (or the byte size matching the cipher) and paste it exactly
  2. Ensure the string is valid standard base64 with correct padding
  3. Match the decoded key length to the cipher's key size (16/24/32 bytes depending on cipher)
  4. Keep server and user keys distinct — each user needs its own key

Example fix

// before
{"users": [{"name": "alice", "password": "plain-text-secret"}]}
// after
{"users": [{"name": "alice", "password": "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY="}]}
Defensive patterns

Strategy: validation

Validate before calling

for u in &svr["users"].as_array().unwrap() {
    let decoded = base64::decode(u["password"].as_str().unwrap()).expect("users[].password must be base64");
    assert!(decoded.len() == 16 || decoded.len() == 32, "decoded key length {} invalid", decoded.len());
}

Type guard

fn is_valid_user_key(pw: &str) -> bool {
    base64::decode(pw).map(|k| k.len() == 16 || k.len() == 32).unwrap_or(false)
}

Try / catch

match ServerUser::with_encoded_key(name, pw) {
    Ok(u) => add(u),
    Err(_) => eprintln!("user '{name}' key must be base64 of a 16/32-byte key"),
}

Prevention

When it happens

Trigger: Loading a config with a `users: [{"name": ..., "password": ...}]` array where a user's `password` is not valid base64 or does not decode to the required key size (e.g. 32 bytes for 2022-blake3-aes-256-gcm).

Common situations: Users pasting plain-text passwords where base64 keys are required; truncated base64 strings from copy-paste; padding/whitespace corruption; generating keys with the wrong `openssl rand -base64` byte count for the cipher.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of shadowsocks/shadowsocks-rust@8eb0f0a65b (2026-09-09). Data as JSON: /api/errors/6f83208738207eda. Report an issue: GitHub.