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

  1. Supply a 32-byte raw identity/PSK for AES-256-GCM (44-character base64 of 32 bytes).
  2. Match method and key size consistently: 16-byte ipsk with AES-128 branch, 32-byte with AES-256 branch.
  3. Validate all configured PSK lengths at startup, before any packet is sent.
  4. 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

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.