use aes::cipher::block_padding::Pkcs7;
use aes::cipher::{BlockDecryptMut, BlockSizeUser, KeyIvInit};
use aes::Aes256;
use crc64::crc64;
use std::cell::RefCell;
use std::io::{Cursor, Error, ErrorKind, Read, Result, Seek, SeekFrom};
use crate::keychain::{FeaturePoint, Keychain};
type Aes256CbcDec = cbc::Decryptor<Aes256>;
pub trait SeekRead: Seek + Read {}
impl<T> SeekRead for T where T: Seek + Read {}
pub fn record_decoder<'a, R>(
reader: R,
record_type: u8,
version: u8,
keychain: &RefCell<Keychain>,
size: u16,
) -> Box<dyn SeekRead + 'a>
where
R: Read + Seek + 'a,
{
match version {
0..=6 => Box::new(reader),
7..=12 => Box::new(XorDecoder::new(reader, record_type)),
_ => {
let feature_point = FeaturePoint::from_record_type(record_type, version);
match feature_point {
FeaturePoint::PlaintextFeature => Box::new(XorDecoder::new(reader, record_type)),
_ => {
let pair = keychain
.borrow()
.get(&feature_point)
.map(|value| (value.0.clone(), value.1.clone()));
match pair {
Some(value) => {
let aes_reader = AesDecoder::new(
XorDecoder::new(reader, record_type),
&value.0,
&value.1,
size - 2, );
keychain.borrow_mut().insert(
feature_point,
(aes_reader.next_iv.clone(), value.1.clone()),
);
Box::new(aes_reader)
}
None => Box::new(XorDecoder::new(reader, record_type)),
}
}
}
}
}
}
pub struct XorDecoder<R> {
reader: R,
key: [u8; 8],
start_position: u64,
decode_position: usize,
}
impl<R: Read + Seek> XorDecoder<R> {
pub fn new(mut reader: R, record_type: u8) -> Self {
let mut first_byte = [0u8];
reader.read_exact(&mut first_byte).unwrap();
let first_byte = first_byte[0];
let start_position = reader.stream_position().unwrap();
let magic: u64 = 0x123456789ABCDEF0;
let key = crc64(
first_byte.overflowing_add(record_type).0 as u64,
&magic.overflowing_mul(first_byte as u64).0.to_le_bytes(),
)
.to_le_bytes();
XorDecoder {
reader,
key,
start_position,
decode_position: 0,
}
}
}
impl<R: Read> Read for XorDecoder<R> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
let bytes_read = self.reader.read(buf)?;
for (i, byte) in buf.iter_mut().enumerate().take(bytes_read) {
*byte ^= self.key[(self.decode_position + i) % 8];
}
self.decode_position += bytes_read;
Ok(bytes_read)
}
}
impl<R: Seek> Seek for XorDecoder<R> {
fn seek(&mut self, pos: SeekFrom) -> Result<u64> {
match pos {
SeekFrom::Start(position) => {
self.decode_position = (position - self.start_position) as usize;
self.reader.seek(pos)
}
SeekFrom::Current(_) => self.reader.seek(pos),
_ => Err(Error::new(ErrorKind::Other, "Unsupported seek")),
}
}
}
pub struct AesDecoder {
buffer: Cursor<Vec<u8>>,
pub next_iv: Vec<u8>,
}
impl AesDecoder {
pub fn new<R: Read>(mut reader: R, iv: &[u8], key: &[u8], size: u16) -> AesDecoder {
let mut buffer = vec![0u8; size.into()];
reader.read_exact(&mut buffer).unwrap();
let next_iv = buffer[buffer.len() - Aes256::block_size()..].to_vec();
let dec: cbc::Decryptor<Aes256> = Aes256CbcDec::new_from_slices(key, iv).unwrap();
let plaintext = dec
.decrypt_padded_mut::<Pkcs7>(&mut buffer)
.unwrap_or_default()
.to_vec();
AesDecoder {
buffer: Cursor::new(plaintext.to_vec()),
next_iv,
}
}
}
impl Read for AesDecoder {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
let _ = self.buffer.read(buf);
Ok(buf.len()) }
}
impl Seek for AesDecoder {
fn seek(&mut self, pos: SeekFrom) -> Result<u64> {
self.buffer.seek(pos)
}
}