tonhowtf/omniget · error · anyhow::Error
AES init
Error message
AES init: {:?} What it means
write_segments_ordered creates an AES-128-CBC decryptor from the EXT-X-KEY key bytes and a computed IV. If the key or IV is not exactly 16 bytes, Aes128CbcDec::new_from_slices fails and this error is raised. It means the encryption metadata is malformed, not that decryption data was wrong.
Solutions
- Log enc.key_bytes.len() and the IV; both must be exactly 16 bytes for AES-128-CBC.
- Verify the key response is binary key data (16 bytes), not HTML/text — re-check the key URI and its response content-type.
- If the playlist declares an IV attribute, use it verbatim instead of computing one from media sequence.
- Re-fetch the playlist/KEY tag if the stream switched variants with a different key.
Example fix
// before
let decryptor = Aes128CbcDec::new_from_slices(&enc.key_bytes, &iv)
.map_err(|e| anyhow::anyhow!("AES init: {:?}", e))?;
// after
if enc.key_bytes.len() != 16 {
anyhow::bail!("AES key is {} bytes, expected 16 (bad key response?)", enc.key_bytes.len());
}
let decryptor = Aes128CbcDec::new_from_slices(&enc.key_bytes, &iv)
.map_err(|e| anyhow::anyhow!("AES init: {e:?} (key {} bytes, iv {} bytes)", enc.key_bytes.len(), iv.len()))?; Defensive patterns
Strategy: validation
Validate before calling
fn valid_aes128_material(key: &[u8], iv: &[u8]) -> bool {
key.len() == 16 && iv.len() == 16
}
if !valid_aes128_material(&enc.key_bytes, &iv) {
anyhow::bail!("bad AES material: key={}B iv={}B", enc.key_bytes.len(), iv.len());
} Try / catch
let decryptor = Aes128CbcDec::new_from_slices(&enc.key_bytes, &iv)
.map_err(|e| anyhow::anyhow!("AES init: {e:?} (key len {}, iv len {})",
enc.key_bytes.len(), iv.len()))?; Prevention
- Validate the fetched key is exactly 16 bytes before constructing the decryptor.
- Prefer the playlist's explicit IV attribute over computing one; log both when they differ.
- Detect non-binary key responses (HTML/text) by checking length/content-type.
- Re-read the active EXT-X-KEY when the playlist updates mid-stream.
When it happens
Trigger: Key fetched from the key URI is not 16 bytes (e.g., HTML error body saved as the key, or key URL serves a wrapper), or the computed IV/declared IV has the wrong length.
Common situations: Key endpoint returned an error page with 200 status; METHOD=AES-128 playlist with an unusual/implicit IV the compute_iv logic mishandles; playlist variant switching to a different KEY mid-download.
Related errors
- HTTP fetching AES key
- Failed to fetch AES key after
- AES decrypt
- Extension playlist is
- Download cancelled by user
AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12).
Data as JSON: /api/errors/bed42af5af630bda.
Report an issue: GitHub.
Appendix: source
Thrown at src-tauri/omniget-core/src/core/hls_downloader.rs:677
while let Some((idx, data)) = rx.recv().await {
pending.insert(idx, data);
while let Some(segment_data) = pending.remove(&next_expected) {
// The image wrapper, when present, sits outside the encryption:
// it has to come off before the AES-128 block decryption runs.
let payload_start = image_wrapper_offset(&segment_data);
if let Some(enc) = encryption {
use aes::cipher::{block_padding::Pkcs7, BlockDecryptMut, KeyIvInit};
type Aes128CbcDec = cbc::Decryptor<aes::Aes128>;
let iv = compute_iv(enc, next_expected, media_sequence);
let mut buf = segment_data;
if payload_start > 0 {
buf.drain(..payload_start);
}
let decryptor = Aes128CbcDec::new_from_slices(&enc.key_bytes, &iv)
.map_err(|e| anyhow::anyhow!("AES init: {:?}", e))?;
let decrypted = decryptor
.decrypt_padded_mut::<Pkcs7>(&mut buf)
.map_err(|e| anyhow::anyhow!("AES decrypt: {:?}", e))?;
file.write_all(decrypted)?;
} else {
file.write_all(&segment_data[payload_start..])?;
}
next_expected += 1;
}
}
file.flush()?;
if next_expected < total_segments {
anyhow::bail!(
"Only {} of {} segments were written",
next_expected,
total_segmentsView on GitHub (pinned to 8600b91f42)