shadowsocks/shadowsocks-rust · error
AES-256 init
Error message
AES-256 init
What it means
Panic from `Aes256::new_from_slice(ipsk).expect("AES-256 init")` in UDP AEAD-2022 `encrypt_message` (AES-256 branch). The identity PSK must be exactly 32 bytes for `Aes256::new_from_slice`; the panic means a wrong-length ipsk was supplied with method `AEAD2022_BLAKE3_AES_256_GCM`.
Source
Thrown at crates/shadowsocks/src/relay/udprelay/aead_2022.rs:233
let nonce = &packet_header[4..16];
if eih_len > 0 {
message = &mut message[eih_len..];
}
cipher.encrypt_packet(nonce, message);
// [SessionID + PacketID] is encrypted with AES-ECB with PSK
// No padding is required because these 2 fields are 128-bits, which is exactly the same as AES's block size
match method {
CipherKind::AEAD2022_BLAKE3_AES_128_GCM => {
let cipher = Aes128::new_from_slice(ipsk).expect("AES-128 init");
let block = <&mut Block as TryFrom<&mut [u8]>>::try_from(packet_header)
.expect("Packet header length mismatch");
cipher.encrypt_block(block);
}
CipherKind::AEAD2022_BLAKE3_AES_256_GCM => {
let cipher = Aes256::new_from_slice(ipsk).expect("AES-256 init");
let block = <&mut Block as TryFrom<&mut [u8]>>::try_from(packet_header)
.expect("Packet header length mismatch");
cipher.encrypt_block(block);
}
_ => unreachable!("{} is not an AES-*-GCM cipher", method),
}
}
_ => unreachable!("{} is not an AEAD 2022 cipher", method),
}
}
fn decrypt_message(
_context: &Context,
method: CipherKind,
key: &[u8],
packet: &mut [u8],
user_manager: Option<&ServerUserManager>,
) -> ProtocolResult<Option<Arc<ServerUser>>> {View on GitHub (pinned to 8eb0f0a65b)
Solutions
- Supply a 32-byte raw identity/PSK for AES-256-GCM (44-character base64 of 32 bytes).
- Match method and key size consistently: 16-byte ipsk with AES-128 branch, 32-byte with AES-256 branch.
- Validate all configured PSK lengths at startup, before any packet is sent.
- Replace the expect with an explicit length assertion including the actual length for faster diagnosis.
Example fix
// before
let cipher = Aes256::new_from_slice(ipsk).expect("AES-256 init");
// after
assert_eq!(ipsk.len(), 32, "AEAD2022_AES_256_GCM identity PSK must be 32 bytes, got {}", ipsk.len());
let cipher = Aes256::new_from_slice(ipsk).expect("AES-256 init"); Defensive patterns
Strategy: validation
Validate before calling
if matches!(method, CipherKind::AEAD2022_BLAKE3_AES_256_GCM) && ipsk.len() != 32 {
return Err(format!("identity PSK must be 32 bytes for AES-256-GCM, got {}", ipsk.len()));
} Type guard
fn is_valid_ipsk256(ipsk: &[u8]) -> bool { ipsk.len() == 32 } Prevention
- Check all configured PSK lengths at config load time.
- Use 44-char base64 (32 raw bytes) keys for AES-256-GCM.
- Guard against mixing 128-bit keys into 256-bit methods in config management code.
When it happens
Trigger: Calling `encrypt_message` (or the client/server payload wrappers) with `method = AEAD2022_BLAKE3_AES_256_GCM` and an `ipsk` shorter/longer than 32 bytes — e.g. a 16-byte identity key from a 128-bit setup or a raw password string.
Common situations: Mixing 128-bit identity keys with a 256-bit method in config; passing the wrong array element when multiple PSKs are configured; pasting a truncated base64 key into the identity-PSK field.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
AI-assisted analysis of shadowsocks/shadowsocks-rust@8eb0f0a65b (2026-09-09).
Data as JSON: /api/errors/8ab94ebe4d612503.
Report an issue: GitHub.