Skip to main content

vsd_mp4/decrypt/
hls.rs

1use cipher::{BlockModeDecrypt, KeyIvInit};
2
3type Aes128Cbc = cbc::Decryptor<aes::Aes128>;
4
5/// A decrypter for HTTP Live Streaming (HLS) AES-128 encrypted segments.
6///
7/// In HLS AES-128, the entire segment file is encrypted using AES-128 in Cipher Block
8/// Chaining (CBC) mode with PKCS7 padding.
9#[derive(Clone)]
10pub struct HlsAes128Decrypter {
11    key: [u8; 16],
12    iv: [u8; 16],
13}
14
15impl HlsAes128Decrypter {
16    /// Creates a new `HlsAes128Decrypter` with the given key and IV.
17    pub fn new(key: &[u8; 16], iv: &[u8; 16]) -> Self {
18        Self { key: *key, iv: *iv }
19    }
20
21    /// Increments the initialization vector (IV) by 1.
22    pub fn increment_iv(&mut self) {
23        self.iv = (u128::from_be_bytes(self.iv) + 1).to_be_bytes();
24    }
25
26    /// Decrypts the given encrypted segment.
27    pub fn decrypt(&self, mut input: Vec<u8>) -> Vec<u8> {
28        let slice_len = {
29            let slice = Aes128Cbc::new((&self.key).into(), (&self.iv).into())
30                .decrypt_padded::<cipher::block_padding::Pkcs7>(&mut input)
31                .unwrap();
32            slice.len()
33        };
34
35        input.truncate(slice_len);
36        input
37    }
38}
39
40/// A decrypter for HTTP Live Streaming (HLS) SAMPLE-AES encrypted segments.
41///
42/// In HLS SAMPLE-AES, only media samples (e.g., individual audio or video frames) are
43/// encrypted, while container metadata and structural headers remain unencrypted.
44#[derive(Clone)]
45pub struct HlsSampleAesDecrypter {
46    key: [u8; 16],
47    iv: [u8; 16],
48}
49
50impl HlsSampleAesDecrypter {
51    /// Creates a new `HlsSampleAesDecrypter` with the given key and IV.
52    pub fn new(key: &[u8; 16], iv: &[u8; 16]) -> Self {
53        Self { key: *key, iv: *iv }
54    }
55
56    /// Increments the initialization vector (IV) by 1.
57    pub fn increment_iv(&mut self) {
58        self.iv = (u128::from_be_bytes(self.iv) + 1).to_be_bytes();
59    }
60
61    /// Decrypts the given encrypted segment.
62    pub fn decrypt(&self, input: Vec<u8>) -> Vec<u8> {
63        let mut input = std::io::Cursor::new(input);
64        let mut output = Vec::new();
65        iori_ssa::decrypt(&mut input, &mut output, self.key, self.iv).unwrap();
66        output
67    }
68}