use std::io::{Cursor, Read};
use crate::{
Result,
ValueEncoder,
ValueDecoder,
HeaderCoding,
header::version1::{
CompressionHeader,
DescriptionHeader,
EncryptionHeader,
HashHeader,
},
ZffError,
ZffErrorKind,
Encryption,
DEFAULT_LENGTH_HEADER_IDENTIFIER,
DEFAULT_LENGTH_VALUE_HEADER_LENGTH,
HEADER_IDENTIFIER_MAIN_HEADER,
HEADER_IDENTIFIER_ENCRYPTED_MAIN_HEADER,
ERROR_HEADER_DECODER_MAIN_HEADER_ENCRYPTED,
ERROR_HEADER_DECODER_MISMATCH_IDENTIFIER,
ERROR_HEADER_DECODER_MAIN_HEADER_NOT_ENCRYPTED,
};
use byteorder::{ReadBytesExt, BigEndian};
#[derive(Debug,Clone)]
pub struct MainHeader {
version: u8,
encryption_header: Option<EncryptionHeader>,
compression_header: CompressionHeader,
description_header: DescriptionHeader,
hash_header: HashHeader,
chunk_size: u8,
signature_flag: u8,
segment_size: u64,
number_of_segments: u64,
unique_identifier: i64,
length_of_data: u64,
}
impl MainHeader {
#[allow(clippy::too_many_arguments)]
pub fn new(
version: u8,
encryption_header: Option<EncryptionHeader>,
compression_header: CompressionHeader,
description_header: DescriptionHeader,
hash_header: HashHeader,
chunk_size: u8,
signature_flag: u8,
segment_size: u64,
number_of_segments: u64,
unique_identifier: i64,
length_of_data: u64) -> MainHeader {
Self {
version,
encryption_header,
compression_header,
description_header,
hash_header,
chunk_size,
signature_flag,
segment_size,
number_of_segments,
unique_identifier,
length_of_data,
}
}
pub fn encrypted_header_identifier() -> u32 {
HEADER_IDENTIFIER_ENCRYPTED_MAIN_HEADER
}
fn encode_encrypted_header<K>(&self, key: K) -> Result<Vec<u8>>
where
K: AsRef<[u8]>
{
let mut vec = vec![self.version];
let encryption_header = match &self.encryption_header {
None => return Err(ZffError::new(ZffErrorKind::MissingEncryptionHeader, "")),
Some(header) => {
header
}
};
let encryption_flag: u8 = 2;
vec.push(encryption_flag);
vec.append(&mut encryption_header.encode_directly());
let mut data_to_encrypt = Vec::new();
data_to_encrypt.append(&mut self.encode_content());
let encrypted_data = Encryption::encrypt_header(
key, data_to_encrypt,
encryption_header.nonce(),
encryption_header.algorithm()
)?;
vec.append(&mut encrypted_data.encode_directly());
Ok(vec)
}
fn check_encrypted_identifier<R: Read>(data: &mut R) -> bool {
let identifier = match data.read_u32::<BigEndian>() {
Ok(val) => val,
Err(_) => return false,
};
identifier == Self::encrypted_header_identifier()
}
pub fn decode_encrypted_header_with_password<R, P>(data: &mut R, password: P) -> Result<MainHeader>
where
R: Read,
P: AsRef<[u8]>,
{
if !Self::check_encrypted_identifier(data) {
return Err(ZffError::new(ZffErrorKind::HeaderDecodeMismatchIdentifier, ERROR_HEADER_DECODER_MISMATCH_IDENTIFIER));
};
let header_length = Self::decode_header_length(data)? as usize;
let mut header_content = vec![0u8; header_length-DEFAULT_LENGTH_HEADER_IDENTIFIER-DEFAULT_LENGTH_VALUE_HEADER_LENGTH];
data.read_exact(&mut header_content)?;
let mut cursor = Cursor::new(header_content);
let header_version = u8::decode_directly(&mut cursor)?;
let encryption_flag = u8::decode_directly(&mut cursor)?;
if encryption_flag != 2 {
return Err(ZffError::new(ZffErrorKind::HeaderDecodeEncryptedHeader, ERROR_HEADER_DECODER_MAIN_HEADER_NOT_ENCRYPTED));
}
let encryption_header = EncryptionHeader::decode_directly(&mut cursor)?;
let encrypted_data = Vec::<u8>::decode_directly(&mut cursor)?;
let encryption_key = encryption_header.decrypt_encryption_key(password)?;
let nonce = encryption_header.nonce();
let algorithm = encryption_header.algorithm();
let decrypted_data = Encryption::decrypt_header(encryption_key, encrypted_data, nonce, algorithm)?;
let mut cursor = Cursor::new(decrypted_data);
let (compression_header,
description_header,
hash_header,
chunk_size,
signature_flag,
segment_size,
number_of_segments,
unique_identifier,
length_of_data) = Self::decode_inner_content(&mut cursor)?;
let main_header = Self::new(
header_version,
Some(encryption_header),
compression_header,
description_header,
hash_header,
chunk_size,
signature_flag,
segment_size,
number_of_segments,
unique_identifier,
length_of_data);
Ok(main_header)
}
pub fn encode_encrypted_header_directly<K>(&self, key: K) -> Result<Vec<u8>>
where
K: AsRef<[u8]>,
{
let mut vec = Vec::new();
let mut encoded_header = self.encode_encrypted_header(key)?;
let identifier = HEADER_IDENTIFIER_ENCRYPTED_MAIN_HEADER;
let encoded_header_length = 4 + 8 + (encoded_header.len() as u64); vec.append(&mut identifier.to_be_bytes().to_vec());
vec.append(&mut encoded_header_length.to_le_bytes().to_vec());
vec.append(&mut encoded_header);
Ok(vec)
}
fn encode_content(&self) -> Vec<u8> {
let mut vec = Vec::new();
vec.append(&mut self.compression_header.encode_directly());
vec.append(&mut self.description_header.encode_directly());
vec.append(&mut self.hash_header.encode_directly());
vec.push(self.chunk_size);
vec.push(self.signature_flag);
vec.append(&mut self.segment_size.encode_directly());
vec.append(&mut self.number_of_segments.encode_directly());
vec.append(&mut self.unique_identifier.encode_directly());
vec.append(&mut self.length_of_data.encode_directly());
vec
}
#[allow(clippy::type_complexity)]
fn decode_inner_content<R: Read>(inner_content: &mut R) -> Result<(
CompressionHeader,
DescriptionHeader,
HashHeader,
u8, // chunk size
u8, // signature flag
u64, // segment size
u64, // number of segments
i64, // unique identifier
u64, // length of data
)>{
let compression_header = CompressionHeader::decode_directly(inner_content)?;
let description_header = DescriptionHeader::decode_directly(inner_content)?;
let hash_header = HashHeader::decode_directly(inner_content)?;
let chunk_size = u8::decode_directly(inner_content)?;
let signature_flag = u8::decode_directly(inner_content)?;
let segment_size = u64::decode_directly(inner_content)?;
let number_of_segments = u64::decode_directly(inner_content)?;
let unique_identifier = i64::decode_directly(inner_content)?;
let length_of_data = u64::decode_directly(inner_content)?;
let inner_content = (
compression_header,
description_header,
hash_header,
chunk_size,
signature_flag,
segment_size,
number_of_segments,
unique_identifier,
length_of_data);
Ok(inner_content)
}
pub fn set_length_of_data(&mut self, len: u64) {
self.length_of_data = len;
}
pub fn set_hash_header(&mut self, hash_header: HashHeader) {
self.hash_header = hash_header;
}
pub fn chunk_size(&self) -> usize {
1<<self.chunk_size
}
pub fn segment_size(&self) -> u64 {
self.segment_size
}
pub fn get_encoded_size(&self) -> usize {
self.encode_directly().len()
}
pub fn get_encrypted_encoded_size<K>(&self, key: K) -> Result<usize>
where
K: AsRef<[u8]>,
{
Ok(self.encode_encrypted_header_directly(key)?.len())
}
pub fn has_signature(&self) -> bool {
self.signature_flag != 0
}
pub fn set_acquisition_end(&mut self, timestamp: u64) {
self.description_header.set_acquisition_end(timestamp);
}
pub fn compression_header(&self) -> &CompressionHeader {
&self.compression_header
}
pub fn encryption_header(&self) -> &Option<EncryptionHeader> {
&self.encryption_header
}
pub fn description_header(&self) -> &DescriptionHeader {
&self.description_header
}
pub fn hash_header(&self) -> &HashHeader {
&self.hash_header
}
pub fn length_of_data(&self) -> u64 {
self.length_of_data
}
pub fn unique_identifier(&self) -> i64 {
self.unique_identifier
}
pub fn set_number_of_segments(&mut self, value: u64) {
self.number_of_segments = value
}
pub fn number_of_segments(&self) -> u64 {
self.number_of_segments
}
}
impl HeaderCoding for MainHeader {
type Item = MainHeader;
fn identifier() -> u32 {
HEADER_IDENTIFIER_MAIN_HEADER
}
fn version(&self) -> u8 {
self.version
}
fn encode_header(&self) -> Vec<u8> {
let mut vec = vec![self.version];
match &self.encryption_header {
None => {
let encryption_flag: u8 = 0;
vec.push(encryption_flag);
},
Some(header) => {
let encryption_flag: u8 = 1;
vec.push(encryption_flag);
vec.append(&mut header.encode_directly());
},
};
vec.append(&mut self.encode_content());
vec
}
fn decode_content(data: Vec<u8>) -> Result<MainHeader> {
let mut cursor = Cursor::new(data);
let version = u8::decode_directly(&mut cursor)?;
let encryption_flag = u8::decode_directly(&mut cursor)?;
let encryption_header = match encryption_flag {
0 => None,
1 => Some(EncryptionHeader::decode_directly(&mut cursor)?),
_ => return Err(ZffError::new(ZffErrorKind::HeaderDecodeEncryptedHeader, ERROR_HEADER_DECODER_MAIN_HEADER_ENCRYPTED))
};
let (compression_header,
description_header,
hash_header,
chunk_size,
signature_flag,
segment_size,
number_of_segments,
unique_identifier,
length_of_data) = Self::decode_inner_content(&mut cursor)?;
let main_header = Self::new(
version,
encryption_header,
compression_header,
description_header,
hash_header,
chunk_size,
signature_flag,
segment_size,
number_of_segments,
unique_identifier,
length_of_data);
Ok(main_header)
}
}