2015-06-23 14:38:29 +00:00
|
|
|
use std::io;
|
2018-07-30 11:18:43 +00:00
|
|
|
|
2022-07-27 21:31:11 +00:00
|
|
|
use aes::cipher::{KeyIvInit, StreamCipher, StreamCipherSeek};
|
|
|
|
|
|
|
|
type Aes128Ctr = ctr::Ctr128BE<aes::Aes128>;
|
2015-06-23 14:38:29 +00:00
|
|
|
|
2019-09-16 19:00:09 +00:00
|
|
|
use librespot_core::audio_key::AudioKey;
|
2015-06-23 14:38:29 +00:00
|
|
|
|
2018-07-30 11:18:43 +00:00
|
|
|
const AUDIO_AESIV: [u8; 16] = [
|
2019-10-08 09:31:18 +00:00
|
|
|
0x72, 0xe0, 0x67, 0xfb, 0xdd, 0xcb, 0xcf, 0x77, 0xeb, 0xe8, 0xbc, 0x64, 0x3f, 0x63, 0x0d, 0x93,
|
2018-02-26 01:50:41 +00:00
|
|
|
];
|
2015-06-23 14:38:29 +00:00
|
|
|
|
2016-01-02 15:19:39 +00:00
|
|
|
pub struct AudioDecrypt<T: io::Read> {
|
2022-01-02 23:13:28 +00:00
|
|
|
// a `None` cipher is a convenience to make `AudioDecrypt` pass files unaltered
|
|
|
|
cipher: Option<Aes128Ctr>,
|
2015-06-23 14:38:29 +00:00
|
|
|
reader: T,
|
|
|
|
}
|
|
|
|
|
2016-01-02 15:19:39 +00:00
|
|
|
impl<T: io::Read> AudioDecrypt<T> {
|
2022-01-02 23:13:28 +00:00
|
|
|
pub fn new(key: Option<AudioKey>, reader: T) -> AudioDecrypt<T> {
|
2022-07-27 21:31:11 +00:00
|
|
|
let cipher = if let Some(key) = key {
|
|
|
|
Aes128Ctr::new_from_slices(&key.0, &AUDIO_AESIV).ok()
|
|
|
|
} else {
|
|
|
|
// some files are unencrypted
|
|
|
|
None
|
|
|
|
};
|
2022-01-02 23:13:28 +00:00
|
|
|
|
2018-07-30 11:18:43 +00:00
|
|
|
AudioDecrypt { cipher, reader }
|
2015-06-23 14:38:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-02 15:19:39 +00:00
|
|
|
impl<T: io::Read> io::Read for AudioDecrypt<T> {
|
2015-06-23 14:38:29 +00:00
|
|
|
fn read(&mut self, output: &mut [u8]) -> io::Result<usize> {
|
2019-10-08 09:31:18 +00:00
|
|
|
let len = self.reader.read(output)?;
|
2015-06-23 14:38:29 +00:00
|
|
|
|
2022-01-02 23:13:28 +00:00
|
|
|
if let Some(ref mut cipher) = self.cipher {
|
|
|
|
cipher.apply_keystream(&mut output[..len]);
|
|
|
|
}
|
2015-06-23 14:38:29 +00:00
|
|
|
|
|
|
|
Ok(len)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-02 15:19:39 +00:00
|
|
|
impl<T: io::Read + io::Seek> io::Seek for AudioDecrypt<T> {
|
2015-06-23 17:34:48 +00:00
|
|
|
fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
|
2019-10-08 09:31:18 +00:00
|
|
|
let newpos = self.reader.seek(pos)?;
|
2015-06-23 17:34:48 +00:00
|
|
|
|
2022-01-02 23:13:28 +00:00
|
|
|
if let Some(ref mut cipher) = self.cipher {
|
|
|
|
cipher.seek(newpos);
|
|
|
|
}
|
2015-06-23 17:34:48 +00:00
|
|
|
|
2018-07-30 11:18:43 +00:00
|
|
|
Ok(newpos)
|
2015-06-23 14:38:29 +00:00
|
|
|
}
|
|
|
|
}
|