use std::io; use aes::cipher::{KeyIvInit, StreamCipher, StreamCipherSeek}; type Aes128Ctr = ctr::Ctr128BE; use librespot_core::audio_key::AudioKey; const AUDIO_AESIV: [u8; 16] = [ 0x72, 0xe0, 0x67, 0xfb, 0xdd, 0xcb, 0xcf, 0x77, 0xeb, 0xe8, 0xbc, 0x64, 0x3f, 0x63, 0x0d, 0x93, ]; pub struct AudioDecrypt { // a `None` cipher is a convenience to make `AudioDecrypt` pass files unaltered cipher: Option, reader: T, } impl AudioDecrypt { pub fn new(key: Option, reader: T) -> AudioDecrypt { let cipher = if let Some(key) = key { Aes128Ctr::new_from_slices(&key.0, &AUDIO_AESIV).ok() } else { // some files are unencrypted None }; AudioDecrypt { cipher, reader } } } impl io::Read for AudioDecrypt { fn read(&mut self, output: &mut [u8]) -> io::Result { let len = self.reader.read(output)?; if let Some(ref mut cipher) = self.cipher { cipher.apply_keystream(&mut output[..len]); } Ok(len) } } impl io::Seek for AudioDecrypt { fn seek(&mut self, pos: io::SeekFrom) -> io::Result { let newpos = self.reader.seek(pos)?; if let Some(ref mut cipher) = self.cipher { cipher.seek(newpos); } Ok(newpos) } }