zff/header/version2/
object_header.rs

1// - STD
2use std::io::{Cursor, Read};
3use std::fmt;
4use std::cmp::{PartialEq,Eq};
5use std::hash::{Hash, Hasher};
6
7// - internal
8use crate::{
9	Result,
10	HeaderCoding,
11	Encryption,
12	ValueEncoder,
13	ValueDecoder,
14	ZffError,
15	ZffErrorKind,
16	SignatureFlag,
17};
18
19use crate::{
20	ERROR_HEADER_DECODER_MISMATCH_IDENTIFIER,
21	DEFAULT_LENGTH_VALUE_HEADER_LENGTH,
22	DEFAULT_LENGTH_HEADER_IDENTIFIER,
23	HEADER_IDENTIFIER_OBJECT_HEADER,
24	ERROR_INVALID_SIGNATURE_FLAG_VALUE,
25	ERROR_INVALID_OBJECT_TYPE_FLAG_VALUE,
26};
27
28use crate::header::{
29	EncryptionHeader,
30	CompressionHeader,
31	DescriptionHeader,
32};
33
34/// Each object starts with a [ObjectHeader]. The [ObjectHeader] contains several metadata of the appropriate underlying object.
35/// The following metadata are stored in an [ObjectHeader]:
36/// - The appropriate number of the objects (the first object always starts with 1)
37/// - An [crate::header::EncryptionHeader], if an encryption was used.
38/// - A [crate::header::CompressionHeader], containing the appropriate compression information
39/// - A flag, if a signature method was used.
40/// - A [crate::header::DescriptionHeader] for this object.
41/// - The [ObjectType] of this object. 
42#[derive(Debug,Clone)]
43pub struct ObjectHeader {
44	version: u8,
45	object_number: u64,
46	encryption_header: Option<EncryptionHeader>,
47	compression_header: CompressionHeader,
48	signature_flag: SignatureFlag,
49	description_header: DescriptionHeader,
50	object_type: ObjectType
51}
52
53impl ObjectHeader {
54	/// creates a new object with the given values
55	pub fn new(version: u8,
56		object_number: u64,
57		encryption_header: Option<EncryptionHeader>,
58		compression_header: CompressionHeader,
59		signature_flag: SignatureFlag,
60		description_header: DescriptionHeader,
61		object_type: ObjectType) -> ObjectHeader {
62		Self {
63			version,
64			object_number,
65			encryption_header,
66			compression_header,
67			signature_flag,
68			description_header,
69			object_type,
70		}
71	}
72
73	/// sets the object number
74	pub fn set_object_number(&mut self, object_number: u64) {
75		self.object_number = object_number
76	}
77	
78	/// returns the object number
79	pub fn object_number(&self) -> u64 {
80		self.object_number
81	}
82	
83	/// returns the [crate::header::DescriptionHeader]
84	pub fn description_header(&self) -> DescriptionHeader {
85		self.description_header.clone()
86	}
87	
88	/// returns the [ObjectType]
89	pub fn object_type(&self) -> ObjectType {
90		self.object_type.clone()
91	}
92
93	/// returns a reference to the underlying [crate::header::EncryptionHeader], if available.
94	pub fn encryption_header(&self) -> Option<&EncryptionHeader> {
95		self.encryption_header.as_ref()
96	}
97
98	/// returns the underlying [crate::header::CompressionHeader]
99	pub fn compression_header(&self) -> CompressionHeader {
100		self.compression_header.clone()
101	}
102
103	/// returns, if the chunks has a ed25519 signature or not.
104	pub fn has_per_chunk_signatures(&self) -> bool {
105		matches!(&self.signature_flag, SignatureFlag::PerChunkSignatures)
106	}
107
108	/// checks if a signature method was used. Returns true if and false if not.
109	pub fn has_hash_signatures(&self) -> bool {
110		!matches!(&self.signature_flag, SignatureFlag::NoSignatures)
111	}
112
113	/// returns the signature flag
114	pub fn signature_flag(&self) -> &SignatureFlag {
115		&self.signature_flag
116	}
117
118	/// encodes the object header to a ```Vec<u8>```. The encryption flag will be set to 2.
119	/// # Error
120	/// The method returns an error, if the encryption header is missing (=None).
121	/// The method returns an error, if the encryption fails.
122	pub fn encode_encrypted_header_directly<K>(&self, key: K) -> Result<Vec<u8>>
123	where
124		K: AsRef<[u8]>,
125	{
126		let mut vec = Vec::new();
127		let mut encoded_header = self.encode_encrypted_header(key)?;
128		let identifier = HEADER_IDENTIFIER_OBJECT_HEADER;
129		let encoded_header_length = 4 + 8 + (encoded_header.len() as u64); //4 bytes identifier + 8 bytes for length + length itself
130		vec.append(&mut identifier.to_be_bytes().to_vec());
131		vec.append(&mut encoded_header_length.to_le_bytes().to_vec());
132		vec.append(&mut encoded_header);
133
134		Ok(vec)
135	}
136
137	fn encode_encrypted_header<K>(&self, key: K) -> Result<Vec<u8>>
138	where
139		K: AsRef<[u8]>
140	{
141		let encryption_header = match &self.encryption_header {
142			None => return Err(ZffError::new(ZffErrorKind::MissingEncryptionHeader, "")),
143			Some(header) => {
144				header
145			}
146		};
147		let encryption_flag: u8 = 2;
148
149		let mut vec = Vec::new();
150		vec.append(&mut self.version.encode_directly());
151		vec.append(&mut self.object_number.encode_directly());
152		vec.push(encryption_flag);
153		vec.append(&mut encryption_header.encode_directly());
154
155		let mut data_to_encrypt = Vec::new();
156		data_to_encrypt.append(&mut self.encode_content());
157
158		let encrypted_data = Encryption::encrypt_header(
159			key, data_to_encrypt,
160			encryption_header.nonce(),
161			encryption_header.algorithm()
162			)?;
163		vec.append(&mut encrypted_data.encode_directly());
164		Ok(vec)
165	}
166
167	fn encode_content(&self) -> Vec<u8> {
168		let mut vec = Vec::new();
169		
170		vec.append(&mut self.compression_header.encode_directly());
171		vec.push(self.signature_flag.clone() as u8);
172		vec.append(&mut self.description_header.encode_directly());
173		vec.push(self.object_type.clone() as u8);
174		vec
175	}
176
177	/// decodes the encrypted header with the given password.
178	pub fn decode_encrypted_header_with_password<R, P>(data: &mut R, password: P) -> Result<ObjectHeader>
179	where
180		R: Read,
181		P: AsRef<[u8]>,
182	{
183		if !Self::check_identifier(data) {
184			return Err(ZffError::new(ZffErrorKind::HeaderDecodeMismatchIdentifier, ERROR_HEADER_DECODER_MISMATCH_IDENTIFIER));
185		};
186		let header_length = Self::decode_header_length(data)? as usize;
187		let mut header_content = vec![0u8; header_length-DEFAULT_LENGTH_HEADER_IDENTIFIER-DEFAULT_LENGTH_VALUE_HEADER_LENGTH];
188		data.read_exact(&mut header_content)?;
189		let mut cursor = Cursor::new(header_content);
190		let header_version = u8::decode_directly(&mut cursor)?;
191		let object_number = u64::decode_directly(&mut cursor)?;
192		let encryption_flag = u8::decode_directly(&mut cursor)?;
193		if encryption_flag != 2 {
194			return Err(ZffError::new(ZffErrorKind::HeaderDecodeEncryptedHeader, ""));
195		}
196		let encryption_header = EncryptionHeader::decode_directly(&mut cursor)?;
197		let encrypted_data = Vec::<u8>::decode_directly(&mut cursor)?;
198		let encryption_key = encryption_header.decrypt_encryption_key(password)?;
199		let nonce = encryption_header.nonce();
200		let algorithm = encryption_header.algorithm();
201		let decrypted_data = Encryption::decrypt_header(encryption_key, encrypted_data, nonce, algorithm)?;
202		let mut cursor = Cursor::new(decrypted_data);
203		let (compression_header,
204			signature_flag,
205			description_header,
206			object_type) = Self::decode_inner_content(&mut cursor)?;
207		let object_header = Self::new(
208			header_version,
209			object_number,
210			Some(encryption_header),
211			compression_header,
212			signature_flag,
213			description_header,
214			object_type);
215		Ok(object_header)
216	}
217
218	fn decode_inner_content<R: Read>(inner_content: &mut R) -> Result<(
219		CompressionHeader,
220		SignatureFlag,
221		DescriptionHeader,
222		ObjectType,
223		)> {
224		let compression_header = CompressionHeader::decode_directly(inner_content)?;
225		let signature_flag = match u8::decode_directly(inner_content)? {
226			0 => SignatureFlag::NoSignatures,
227			1 => SignatureFlag::HashValueSignatureOnly,
228			2 => SignatureFlag::PerChunkSignatures,
229			value => return Err(ZffError::new(ZffErrorKind::InvalidFlagValue, format!("{ERROR_INVALID_SIGNATURE_FLAG_VALUE} {value}"))),
230		};
231		let description_header = DescriptionHeader::decode_directly(inner_content)?;
232		let object_type = match u8::decode_directly(inner_content)? {
233			0 => ObjectType::Physical,
234			1 => ObjectType::Logical,
235			value => return Err(ZffError::new(ZffErrorKind::InvalidFlagValue, format!("{ERROR_INVALID_OBJECT_TYPE_FLAG_VALUE}{value}"))),
236		};
237		let inner_content = (
238			compression_header,
239			signature_flag,
240			description_header,
241			object_type);
242		Ok(inner_content)
243	}
244}
245
246/// Defines the [ObjectType], which can be used in zff container.
247#[repr(u8)]
248#[derive(Debug,Clone,Eq,PartialEq,Hash)]
249pub enum ObjectType {
250	/// An object containing a physical dump.
251	Physical = 0,
252	/// An object, containing logical files.
253	Logical = 1,
254}
255
256impl fmt::Display for ObjectType {
257    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
258		let msg = match self {
259			ObjectType::Physical => "Physical",
260			ObjectType::Logical => "Logical",
261		};
262		write!(f, "{}", msg)
263	}
264}
265
266impl HeaderCoding for ObjectHeader {
267	type Item = ObjectHeader;
268	fn identifier() -> u32 {
269		HEADER_IDENTIFIER_OBJECT_HEADER
270	}
271
272	fn version(&self) -> u8 {
273		self.version
274	}
275
276	/// encodes the (header) value/object directly (= without key).
277	fn encode_directly(&self) -> Vec<u8> {
278		let mut vec = Vec::new();
279		let mut encoded_object_number = self.object_number.encode_directly();
280		let mut encoded_header = self.encode_header();
281		let identifier = Self::identifier();
282		let encoded_header_length = (DEFAULT_LENGTH_HEADER_IDENTIFIER + DEFAULT_LENGTH_VALUE_HEADER_LENGTH + encoded_header.len() + encoded_object_number.len() + 1) as u64; //4 bytes identifier + 8 bytes for length + length of encoded content + len of object number + length of version
283		vec.append(&mut identifier.to_be_bytes().to_vec());
284		vec.append(&mut encoded_header_length.to_le_bytes().to_vec());
285		vec.push(self.version);
286		vec.append(&mut encoded_object_number);
287		vec.append(&mut encoded_header);
288		vec
289	}
290
291	fn encode_header(&self) -> Vec<u8> {
292		let mut vec = Vec::new();
293		match &self.encryption_header {
294			None => {
295				let encryption_flag: u8 = 0;
296				vec.push(encryption_flag);
297			},
298			Some(header) => {
299				let encryption_flag: u8 = 1;
300				vec.push(encryption_flag);
301				vec.append(&mut header.encode_directly());
302			},
303		};
304
305		vec.append(&mut self.encode_content());
306
307		vec
308	}
309
310	fn decode_content(data: Vec<u8>) -> Result<ObjectHeader> {
311		let mut cursor = Cursor::new(data);
312		let version = u8::decode_directly(&mut cursor)?;
313		let object_number = u64::decode_directly(&mut cursor)?;
314		//encryption flag:
315		let encryption_flag = u8::decode_directly(&mut cursor)?;
316		let encryption_header = match encryption_flag {
317			0 => None,
318			1 => Some(EncryptionHeader::decode_directly(&mut cursor)?),
319			flag_value => return Err(ZffError::new(ZffErrorKind::HeaderDecodeEncryptedHeader, flag_value.to_string()))
320		};
321		let (compression_header,
322			signature_flag,
323			description_header,
324			object_type) = Self::decode_inner_content(&mut cursor)?;
325
326		let object_header = Self::new(
327			version,
328			object_number,
329			encryption_header,
330			compression_header,
331			signature_flag,
332			description_header,
333			object_type);
334		Ok(object_header)
335	}
336}
337
338impl PartialEq for ObjectHeader {
339    fn eq(&self, other: &Self) -> bool {
340        self.object_number == other.object_number
341    }
342}
343
344impl Eq for ObjectHeader {}
345
346impl Hash for ObjectHeader {
347	fn hash<H: Hasher>(&self, state: &mut H) {
348        self.object_number.hash(state);
349    }
350}