shadowsocks/shadowsocks-rust · error
AES-128
Error message
AES-128
What it means
In the AEAD-2022 EIH (extended identity header) handling, for AES-128 methods the identity sub-key is fed to Aes128::new_from_slice(&identity_sub_key[0..16]).expect("AES-128"). blake3::derive_key always returns 32 bytes, so the 16-byte slice is guaranteed valid — this expect can only fire if derive_key returned a shorter hash or the slice bounds changed, i.e. an internal invariant of the crypto setup is broken.
Source
Thrown at crates/shadowsocks/src/relay/tcprelay/aead_2022.rs:317
// https://github.com/Shadowsocks-NET/shadowsocks-specs/blob/main/2022-2-shadowsocks-2022-extensible-identity-headers.md
let mut cipher = if require_eih {
match self.user_manager {
Some(ref user_manager) => {
// Assume we have at least 1 EIH
if header_chunk.len() < 16 {
error!("expecting EIH, but header chunk len: {}", header_chunk.len());
return Err(ProtocolError::MissingExtendedIdentityHeader).into();
}
let (eih, remain_header_chunk) = header_chunk.split_at_mut(16);
header_chunk = remain_header_chunk;
let key_material = [key, salt].concat();
let identity_sub_key = blake3::derive_key(AEAD2022_EIH_SUBKEY_CONTEXT, &key_material);
let mut user_hash = Block::from([0u8; 16]);
match self.method {
CipherKind::AEAD2022_BLAKE3_AES_128_GCM => {
let cipher = Aes128::new_from_slice(&identity_sub_key[0..16]).expect("AES-128");
cipher.decrypt_block_b2b(
<&Block as TryFrom<&[u8]>>::try_from(eih).expect("EIH key length mismatch"),
&mut user_hash,
);
}
CipherKind::AEAD2022_BLAKE3_AES_256_GCM => {
let cipher = Aes256::new_from_slice(&identity_sub_key[0..32]).expect("AES-256");
cipher.decrypt_block_b2b(
<&Block as TryFrom<&[u8]>>::try_from(eih).expect("EIH key length mismatch"),
&mut user_hash,
);
}
_ => unreachable!("{} doesn't support EIH", self.method),
}
let user_hash = user_hash.as_slice();
trace!(
"server EIH {:?}, hash: {:?}",View on GitHub (pinned to 8eb0f0a65b)
Solutions
- No user action needed — if you see it, report a bug with the version of shadowsocks-rust and blake3
- If editing the code, propagate a ProtocolError instead of expect
- Pin/verify blake3 crate behavior (derive_key output length) after dependency upgrades
Defensive patterns
Strategy: validation
Validate before calling
debug_assert!(identity_sub_key.len() >= 16, "EIH sub-key too short");
Type guard
fn key_material_ok(k: &[u8]) -> bool { k.len() >= 16 } Try / catch
let cipher = Aes128::new_from_slice(&identity_sub_key[0..16])
.map_err(|_| ProtocolError::InvalidState)?; Prevention
- Pin blake3 crate version in CI and test derive_key output length
- Run AEAD-2022 integration tests after dependency upgrades
- Do not modify the 0..16 slice bounds without adding asserts
When it happens
Trigger: Practically unreachable while blake3 derive_key yields ≥16 bytes; could only panic if the code slicing (0..16) is modified, or a substitute KDF returns less material.
Common situations: Developers hitting this after modifying the key-derivation code or bumping blake3/aes crate versions with changed API semantics; not seen in normal operation.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
AI-assisted analysis of shadowsocks/shadowsocks-rust@8eb0f0a65b (2026-09-09).
Data as JSON: /api/errors/c4cd246ca6555123.
Report an issue: GitHub.