dexios_core/
header.rs

1//! The Dexios header is an encrypted file/data header that stores specific information needed for decryption.
2//!
3//! This includes:
4//! * header version
5//! * salt
6//! * nonce
7//! * encryption algorithm
8//! * whether the file was encrypted in "memory" or stream mode
9//!
10//! It allows for serialization, deserialization, and has a convenience function for quickly writing the header to a file.
11//!
12//! # Examples
13//!
14//! ```rust,ignore
15//! let header_bytes: [u8; 64] = [
16//!     222, 2, 14, 1, 12, 1, 142, 88, 243, 144, 119, 187, 189, 190, 121, 90, 211, 56, 185, 14, 76,
17//!     45, 16, 5, 237, 72, 7, 203, 13, 145, 13, 155, 210, 29, 128, 142, 241, 233, 42, 168, 243,
18//!     129, 0, 0, 0, 0, 0, 0, 214, 45, 3, 4, 11, 212, 129, 123, 192, 157, 185, 109, 151, 225, 233,
19//!     161,
20//! ];
21//! let mut cursor = Cursor::new(header_bytes);
22//!
23//! // the cursor may be a file, this is just an example
24//!
25//! let (header, aad) = Header::deserialize(&mut cursor).unwrap();
26//! ```
27//!
28//! ```rust,ignore
29//! let mut output_file = File::create("test").unwrap();
30//!
31//! header.write(&mut output_file).unwrap();
32//! ```
33//!
34
35use crate::{
36    key::{argon2id_hash, balloon_hash},
37    protected::Protected,
38};
39
40use super::primitives::{get_nonce_len, Algorithm, Mode, ENCRYPTED_MASTER_KEY_LEN, SALT_LEN};
41use anyhow::{Context, Result};
42use std::io::{Cursor, Read, Seek, Write};
43
44/// This defines the latest header version, so program's using this can easily stay up to date.
45///
46/// It's also here to just help users keep track
47pub const HEADER_VERSION: HeaderVersion = HeaderVersion::V5;
48
49/// This stores all possible versions of the header
50#[allow(clippy::module_name_repetitions)]
51#[derive(PartialEq, Eq, Clone, Copy, PartialOrd)]
52pub enum HeaderVersion {
53    V1,
54    V2,
55    V3,
56    V4,
57    V5,
58}
59
60impl std::fmt::Display for HeaderVersion {
61    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
62        match self {
63            HeaderVersion::V1 => write!(f, "V1"),
64            HeaderVersion::V2 => write!(f, "V2"),
65            HeaderVersion::V3 => write!(f, "V3"),
66            HeaderVersion::V4 => write!(f, "V4"),
67            HeaderVersion::V5 => write!(f, "V5"),
68        }
69    }
70}
71
72/// This is the Header's type - it contains the specific details that are needed to decrypt the data
73///
74/// It contains the header's version, the "mode" that was used to encrypt the data, and the algorithm used.
75///
76/// This needs to be manually created for encrypting data
77#[allow(clippy::module_name_repetitions)]
78pub struct HeaderType {
79    pub version: HeaderVersion,
80    pub algorithm: Algorithm,
81    pub mode: Mode,
82}
83
84/// This is the `HeaderType` struct, but in the format of raw bytes
85///
86/// This does not need to be used outside of this core library
87struct HeaderTag {
88    pub version: [u8; 2],
89    pub algorithm: [u8; 2],
90    pub mode: [u8; 2],
91}
92
93/// This is the main `Header` struct, and it contains all of the information about the encrypted data
94///
95/// It contains the `HeaderType`, the nonce, and the salt
96///
97/// This needs to be manually created for encrypting data
98pub struct Header {
99    pub header_type: HeaderType,
100    pub nonce: Vec<u8>,
101    pub salt: Option<[u8; SALT_LEN]>, // option as v4+ use the keyslots
102    pub keyslots: Option<Vec<Keyslot>>,
103}
104
105pub const ARGON2ID_LATEST: i32 = 3;
106pub const BLAKE3BALLOON_LATEST: i32 = 5;
107
108
109/// This is in place to make `Keyslot` handling a **lot** easier
110/// You may use the constants `ARGON2ID_LATEST` and `BLAKE3BALLOON_LATEST` for defining versions
111#[derive(Clone, Copy, PartialEq, Eq)]
112pub enum HashingAlgorithm {
113    Argon2id(i32),
114    Blake3Balloon(i32),
115}
116
117impl std::fmt::Display for HashingAlgorithm {
118    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
119        match self {
120            HashingAlgorithm::Argon2id(i) => write!(f, "Argon2id (param v{})", i),
121            HashingAlgorithm::Blake3Balloon(i) => write!(f, "BLAKE3-Balloon (param v{})", i),
122        }
123    }
124}
125
126impl HashingAlgorithm {
127    /// A simple helper function that will hash a value with the appropriate algorithm and version
128    pub fn hash(
129        &self,
130        raw_key: Protected<Vec<u8>>,
131        salt: &[u8; SALT_LEN],
132    ) -> Result<Protected<[u8; 32]>, anyhow::Error> {
133        match self {
134            HashingAlgorithm::Argon2id(i) => match i {
135                1 => argon2id_hash(raw_key, salt, &HeaderVersion::V1),
136                2 => argon2id_hash(raw_key, salt, &HeaderVersion::V2),
137                3 => argon2id_hash(raw_key, salt, &HeaderVersion::V3),
138                _ => Err(anyhow::anyhow!(
139                    "argon2id is not supported with the parameters provided."
140                )),
141            },
142            HashingAlgorithm::Blake3Balloon(i) => match i {
143                4 => balloon_hash(raw_key, salt, &HeaderVersion::V4),
144                5 => balloon_hash(raw_key, salt, &HeaderVersion::V5),
145                _ => Err(anyhow::anyhow!(
146                    "Balloon hashing is not supported with the parameters provided."
147                )),
148            },
149        }
150    }
151}
152
153/// This defines a keyslot that is used with header V4 and above.
154/// A keyslot contains information about the key, and the encrypted key itself
155#[derive(Clone)]
156pub struct Keyslot {
157    pub hash_algorithm: HashingAlgorithm,
158    pub encrypted_key: [u8; ENCRYPTED_MASTER_KEY_LEN],
159    pub nonce: Vec<u8>,
160    pub salt: [u8; SALT_LEN],
161}
162
163impl Keyslot {
164    /// This is used to convert a keyslot into bytes - ideal for writing headers
165    #[must_use]
166    pub fn serialize(&self) -> [u8; 2] {
167        match self.hash_algorithm {
168            HashingAlgorithm::Argon2id(i) => match i {
169                1 => [0xDF, 0xA1],
170                2 => [0xDF, 0xA2],
171                3 => [0xDF, 0xA3],
172                _ => [0x00, 0x00],
173            },
174            HashingAlgorithm::Blake3Balloon(i) => match i {
175                4 => [0xDF, 0xB4],
176                5 => [0xDF, 0xB5],
177                _ => [0x00, 0x00],
178            },
179        }
180    }
181}
182
183impl Header {
184    /// This is a private function (used by other header functions) for returning the `HeaderType`'s raw bytes
185    ///
186    /// It's used for serialization, and has it's own dedicated function as it will be used often
187    fn get_tag(&self) -> HeaderTag {
188        let version = self.serialize_version();
189        let algorithm = self.serialize_algorithm();
190        let mode = self.serialize_mode();
191        HeaderTag {
192            version,
193            algorithm,
194            mode,
195        }
196    }
197
198    /// This is a private function used for serialization
199    ///
200    /// It converts a `HeaderVersion` into the associated raw bytes
201    fn serialize_version(&self) -> [u8; 2] {
202        match self.header_type.version {
203            HeaderVersion::V1 => {
204                let info: [u8; 2] = [0xDE, 0x01];
205                info
206            }
207            HeaderVersion::V2 => {
208                let info: [u8; 2] = [0xDE, 0x02];
209                info
210            }
211            HeaderVersion::V3 => {
212                let info: [u8; 2] = [0xDE, 0x03];
213                info
214            }
215            HeaderVersion::V4 => {
216                let info: [u8; 2] = [0xDE, 0x04];
217                info
218            }
219            HeaderVersion::V5 => {
220                let info: [u8; 2] = [0xDE, 0x05];
221                info
222            }
223        }
224    }
225
226    /// This is used for deserializing raw bytes from a reader into a `Header` struct
227    ///
228    /// This also returns the AAD, read from the header. AAD is only generated in `HeaderVersion::V3` and above - it will be blank in older versions.
229    ///
230    /// The AAD needs to be passed to decryption functions in order to validate the header, and decrypt the data.
231    ///
232    /// The AAD for older versions is empty as no AAD is the default for AEADs, and the header validation was not in place prior to V3.
233    ///
234    /// NOTE: This leaves the cursor at 64 bytes into the buffer, as that is the size of the header
235    ///
236    /// # Examples
237    ///
238    /// ```rust,ignore
239    /// let header_bytes: [u8; 64] = [
240    ///     222, 2, 14, 1, 12, 1, 142, 88, 243, 144, 119, 187, 189, 190, 121, 90, 211, 56, 185, 14, 76,
241    ///     45, 16, 5, 237, 72, 7, 203, 13, 145, 13, 155, 210, 29, 128, 142, 241, 233, 42, 168, 243,
242    ///     129, 0, 0, 0, 0, 0, 0, 214, 45, 3, 4, 11, 212, 129, 123, 192, 157, 185, 109, 151, 225, 233,
243    ///     161,
244    /// ];
245    /// let mut cursor = Cursor::new(header_bytes);
246    ///
247    /// // the cursor may be a file, this is just an example
248    ///
249    /// let (header, aad) = Header::deserialize(&mut cursor).unwrap();
250    /// ```
251    ///
252    #[allow(clippy::too_many_lines)]
253    pub fn deserialize(reader: &mut (impl Read + Seek)) -> Result<(Self, Vec<u8>)> {
254        let mut version_bytes = [0u8; 2];
255        reader
256            .read_exact(&mut version_bytes)
257            .context("Unable to read version from the header")?;
258        reader
259            .seek(std::io::SeekFrom::Current(-2))
260            .context("Unable to seek back to start of header")?;
261
262        let version = match version_bytes {
263            [0xDE, 0x01] => HeaderVersion::V1,
264            [0xDE, 0x02] => HeaderVersion::V2,
265            [0xDE, 0x03] => HeaderVersion::V3,
266            [0xDE, 0x04] => HeaderVersion::V4,
267            [0xDE, 0x05] => HeaderVersion::V5,
268            _ => return Err(anyhow::anyhow!("Error getting version from header")),
269        };
270
271        let header_length: usize = match version {
272            HeaderVersion::V1 | HeaderVersion::V2 | HeaderVersion::V3 => 64,
273            HeaderVersion::V4 => 128,
274            HeaderVersion::V5 => 416,
275        };
276
277        let mut full_header_bytes = vec![0u8; header_length];
278        reader
279            .read_exact(&mut full_header_bytes)
280            .context("Unable to read full bytes of the header")?;
281
282        let mut cursor = Cursor::new(full_header_bytes.clone());
283        cursor
284            .seek(std::io::SeekFrom::Start(2))
285            .context("Unable to seek past version bytes")?; // seek past the version bytes as we already have those
286
287        let mut algorithm_bytes = [0u8; 2];
288        cursor
289            .read_exact(&mut algorithm_bytes)
290            .context("Unable to read algorithm's bytes from header")?;
291
292        let algorithm = match algorithm_bytes {
293            [0x0E, 0x01] => Algorithm::XChaCha20Poly1305,
294            [0x0E, 0x02] => Algorithm::Aes256Gcm,
295            [0x0E, 0x03] => Algorithm::DeoxysII256,
296            _ => return Err(anyhow::anyhow!("Error getting encryption mode from header")),
297        };
298
299        let mut mode_bytes = [0u8; 2];
300        cursor
301            .read_exact(&mut mode_bytes)
302            .context("Unable to read encryption mode's bytes from header")?;
303
304        let mode = match mode_bytes {
305            [0x0C, 0x01] => Mode::StreamMode,
306            [0x0C, 0x02] => Mode::MemoryMode,
307            _ => return Err(anyhow::anyhow!("Error getting cipher mode from header")),
308        };
309
310        let header_type = HeaderType {
311            version,
312            algorithm,
313            mode,
314        };
315
316        let nonce_len = get_nonce_len(&header_type.algorithm, &header_type.mode);
317        let mut salt = [0u8; 16];
318        let mut nonce = vec![0u8; nonce_len];
319
320        let keyslots: Option<Vec<Keyslot>> = match header_type.version {
321            HeaderVersion::V1 | HeaderVersion::V3 => {
322                cursor
323                    .read_exact(&mut salt)
324                    .context("Unable to read salt from header")?;
325                cursor
326                    .read_exact(&mut [0; 16])
327                    .context("Unable to read empty bytes from header")?;
328                cursor
329                    .read_exact(&mut nonce)
330                    .context("Unable to read nonce from header")?;
331                cursor
332                    .read_exact(&mut vec![0u8; 26 - nonce_len])
333                    .context("Unable to read final padding from header")?;
334
335                None
336            }
337            HeaderVersion::V2 => {
338                cursor
339                    .read_exact(&mut salt)
340                    .context("Unable to read salt from header")?;
341                cursor
342                    .read_exact(&mut nonce)
343                    .context("Unable to read nonce from header")?;
344                cursor
345                    .read_exact(&mut vec![0u8; 26 - nonce_len])
346                    .context("Unable to read empty bytes from header")?;
347                cursor
348                    .read_exact(&mut [0u8; 16])
349                    .context("Unable to read final padding from header")?;
350
351                None
352            }
353            HeaderVersion::V4 => {
354                let mut master_key_encrypted = [0u8; 48];
355                let master_key_nonce_len = get_nonce_len(&algorithm, &Mode::MemoryMode);
356                let mut master_key_nonce = vec![0u8; master_key_nonce_len];
357                cursor
358                    .read_exact(&mut salt)
359                    .context("Unable to read salt from header")?;
360                cursor
361                    .read_exact(&mut nonce)
362                    .context("Unable to read nonce from header")?;
363                cursor
364                    .read_exact(&mut vec![0u8; 26 - nonce_len])
365                    .context("Unable to read padding from header")?;
366                cursor
367                    .read_exact(&mut master_key_encrypted)
368                    .context("Unable to read encrypted master key from header")?;
369                cursor
370                    .read_exact(&mut master_key_nonce)
371                    .context("Unable to read master key nonce from header")?;
372                cursor
373                    .read_exact(&mut vec![0u8; 32 - master_key_nonce_len])
374                    .context("Unable to read padding from header")?;
375
376                let keyslot = Keyslot {
377                    encrypted_key: master_key_encrypted,
378                    hash_algorithm: HashingAlgorithm::Blake3Balloon(4),
379                    nonce: master_key_nonce.clone(),
380                    salt,
381                };
382                let keyslots = vec![keyslot];
383                Some(keyslots)
384            }
385            HeaderVersion::V5 => {
386                cursor
387                    .read_exact(&mut nonce)
388                    .context("Unable to read nonce from header")?;
389                cursor
390                    .read_exact(&mut vec![0u8; 26 - nonce_len])
391                    .context("Unable to read padding from header")?; // here we reach the 32 bytes
392
393                let keyslot_nonce_len = get_nonce_len(&algorithm, &Mode::MemoryMode);
394
395                let mut keyslots: Vec<Keyslot> = Vec::new();
396                for _ in 0..4 {
397                    let mut identifier = [0u8; 2];
398                    cursor
399                        .read_exact(&mut identifier)
400                        .context("Unable to read keyslot identifier from header")?;
401
402                    if identifier[..1] != [0xDF] {
403                        continue;
404                    }
405
406                    let mut encrypted_key = [0u8; 48];
407                    let mut nonce = vec![0u8; keyslot_nonce_len];
408                    let mut padding = vec![0u8; 24 - keyslot_nonce_len];
409                    let mut salt = [0u8; SALT_LEN];
410
411                    cursor
412                        .read_exact(&mut encrypted_key)
413                        .context("Unable to read keyslot encrypted bytes from header")?;
414
415                    cursor
416                        .read_exact(&mut nonce)
417                        .context("Unable to read keyslot nonce from header")?;
418
419                    cursor
420                        .read_exact(&mut padding)
421                        .context("Unable to read keyslot padding from header")?;
422
423                    cursor
424                        .read_exact(&mut salt)
425                        .context("Unable to read keyslot salt from header")?;
426
427                    cursor
428                        .read_exact(&mut [0u8; 6])
429                        .context("Unable to read keyslot padding from header")?;
430
431                    let hash_algorithm = match identifier {
432                        [0xDF, 0xA1] => HashingAlgorithm::Argon2id(1),
433                        [0xDF, 0xA2] => HashingAlgorithm::Argon2id(2),
434                        [0xDF, 0xA3] => HashingAlgorithm::Argon2id(3),
435                        [0xDF, 0xB4] => HashingAlgorithm::Blake3Balloon(4),
436                        [0xDF, 0xB5] => HashingAlgorithm::Blake3Balloon(5),
437                        _ => return Err(anyhow::anyhow!("Key hashing algorithm not identified")),
438                    };
439
440                    let keyslot = Keyslot {
441                        hash_algorithm,
442                        encrypted_key,
443                        nonce,
444                        salt,
445                    };
446
447                    keyslots.push(keyslot);
448                }
449
450                Some(keyslots)
451            }
452        };
453
454        let aad = match header_type.version {
455            HeaderVersion::V1 | HeaderVersion::V2 => Vec::<u8>::new(),
456            HeaderVersion::V3 => full_header_bytes.clone(),
457            HeaderVersion::V4 => {
458                let master_key_nonce_len = get_nonce_len(&algorithm, &Mode::MemoryMode);
459                let mut aad = Vec::new();
460
461                // this is for the version/algorithm/mode/salt/nonce
462                aad.extend_from_slice(&full_header_bytes[..48]);
463
464                // this is for the padding that's appended to the end of the master key's nonce
465                // the master key/master key nonce aren't included as they may change
466                // the master key nonce length will be fixed, as otherwise the algorithm has changed
467                // and that requires re-encrypting anyway
468                aad.extend_from_slice(&full_header_bytes[(96 + master_key_nonce_len)..]);
469                aad
470            }
471            HeaderVersion::V5 => {
472                let mut aad = Vec::new();
473                aad.extend_from_slice(&full_header_bytes[..32]);
474                aad
475            }
476        };
477
478        Ok((
479            Header {
480                header_type,
481                nonce,
482                salt: Some(salt),
483                keyslots,
484            },
485            aad,
486        ))
487    }
488
489    /// This is a private function used for serialization
490    ///
491    /// It converts an `Algorithm` into the associated raw bytes
492    fn serialize_algorithm(&self) -> [u8; 2] {
493        match self.header_type.algorithm {
494            Algorithm::XChaCha20Poly1305 => {
495                let info: [u8; 2] = [0x0E, 0x01];
496                info
497            }
498            Algorithm::Aes256Gcm => {
499                let info: [u8; 2] = [0x0E, 0x02];
500                info
501            }
502            Algorithm::DeoxysII256 => {
503                let info: [u8; 2] = [0x0E, 0x03];
504                info
505            }
506        }
507    }
508
509    /// This is a private function used for serialization
510    ///
511    /// It converts a `Mode` into the associated raw bytes
512    fn serialize_mode(&self) -> [u8; 2] {
513        match self.header_type.mode {
514            Mode::StreamMode => {
515                let info: [u8; 2] = [0x0C, 0x01];
516                info
517            }
518            Mode::MemoryMode => {
519                let info: [u8; 2] = [0x0C, 0x02];
520                info
521            }
522        }
523    }
524
525    /// This is a private function (called by `serialize()`)
526    ///
527    /// It serializes V3 headers
528    fn serialize_v3(&self, tag: &HeaderTag) -> Vec<u8> {
529        let padding =
530            vec![0u8; 26 - get_nonce_len(&self.header_type.algorithm, &self.header_type.mode)];
531        let mut header_bytes = Vec::<u8>::new();
532        header_bytes.extend_from_slice(&tag.version);
533        header_bytes.extend_from_slice(&tag.algorithm);
534        header_bytes.extend_from_slice(&tag.mode);
535        header_bytes.extend_from_slice(&self.salt.unwrap());
536        header_bytes.extend_from_slice(&[0; 16]);
537        header_bytes.extend_from_slice(&self.nonce);
538        header_bytes.extend_from_slice(&padding);
539        header_bytes
540    }
541
542    /// This is a private function (called by `serialize()`)
543    ///
544    /// It serializes V4 headers
545    fn serialize_v4(&self, tag: &HeaderTag) -> Vec<u8> {
546        let padding =
547            vec![0u8; 26 - get_nonce_len(&self.header_type.algorithm, &self.header_type.mode)];
548        let padding2 =
549            vec![0u8; 32 - get_nonce_len(&self.header_type.algorithm, &Mode::MemoryMode)];
550
551        let keyslot = self.keyslots.clone().unwrap();
552
553        let mut header_bytes = Vec::<u8>::new();
554        header_bytes.extend_from_slice(&tag.version);
555        header_bytes.extend_from_slice(&tag.algorithm);
556        header_bytes.extend_from_slice(&tag.mode);
557        header_bytes.extend_from_slice(&self.salt.unwrap_or(keyslot[0].salt));
558        header_bytes.extend_from_slice(&self.nonce);
559        header_bytes.extend_from_slice(&padding);
560        header_bytes.extend_from_slice(&keyslot[0].encrypted_key);
561        header_bytes.extend_from_slice(&keyslot[0].nonce);
562        header_bytes.extend_from_slice(&padding2);
563        header_bytes
564    }
565
566    /// This is a private function (called by `serialize()`)
567    ///
568    /// It serializes V5 headers
569    fn serialize_v5(&self, tag: &HeaderTag) -> Vec<u8> {
570        let padding =
571            vec![0u8; 26 - get_nonce_len(&self.header_type.algorithm, &self.header_type.mode)];
572
573        let keyslots = self.keyslots.clone().unwrap();
574
575        let mut header_bytes = Vec::<u8>::new();
576
577        // start of header static info
578        header_bytes.extend_from_slice(&tag.version);
579        header_bytes.extend_from_slice(&tag.algorithm);
580        header_bytes.extend_from_slice(&tag.mode);
581        header_bytes.extend_from_slice(&self.nonce);
582        header_bytes.extend_from_slice(&padding);
583        // end of header static info
584
585        for keyslot in &keyslots {
586            let keyslot_nonce_len = get_nonce_len(&self.header_type.algorithm, &Mode::MemoryMode);
587
588            header_bytes.extend_from_slice(&keyslot.serialize());
589            header_bytes.extend_from_slice(&keyslot.encrypted_key);
590            header_bytes.extend_from_slice(&keyslot.nonce);
591            header_bytes.extend_from_slice(&vec![0u8; 24 - keyslot_nonce_len]);
592            header_bytes.extend_from_slice(&keyslot.salt);
593            header_bytes.extend_from_slice(&[0u8; 6]);
594        }
595
596        for _ in 0..(4 - keyslots.len()) {
597            header_bytes.extend_from_slice(&[0u8; 96]);
598        }
599
600        header_bytes
601    }
602
603    /// This serializes a `Header` struct, and returns the raw bytes
604    ///
605    /// The returned bytes may be used as AAD, or written to a file
606    ///
607    /// NOTE: This should **NOT** be used for validating or creating AAD.
608    ///
609    /// It only has support for V3 headers and above
610    ///
611    /// Create AAD with `create_aad()`.
612    ///
613    /// Use the AAD returned from `deserialize()` for validation.
614    ///
615    /// # Examples
616    ///
617    /// ```rust,ignore
618    /// let header_bytes = header.serialize().unwrap();
619    /// ```
620    ///
621    pub fn serialize(&self) -> Result<Vec<u8>> {
622        let tag = self.get_tag();
623        match self.header_type.version {
624            HeaderVersion::V1 => Err(anyhow::anyhow!(
625                "Serializing V1 headers has been deprecated"
626            )),
627            HeaderVersion::V2 => Err(anyhow::anyhow!(
628                "Serializing V2 headers has been deprecated"
629            )),
630            HeaderVersion::V3 => Ok(self.serialize_v3(&tag)),
631            HeaderVersion::V4 => Ok(self.serialize_v4(&tag)),
632            HeaderVersion::V5 => Ok(self.serialize_v5(&tag)),
633        }
634    }
635
636    #[must_use]
637    pub fn get_size(&self) -> u64 {
638        match self.header_type.version {
639            HeaderVersion::V1 | HeaderVersion::V2 | HeaderVersion::V3 => 64,
640            HeaderVersion::V4 => 128,
641            HeaderVersion::V5 => 416,
642        }
643    }
644
645    /// This is for creating AAD
646    ///
647    /// It only has support for V3 headers and above
648    ///
649    /// It will return the bytes used for AAD
650    /// 
651    /// You may view more about what is used as AAD [here](https://brxken128.github.io/dexios/dexios-core/Headers.html#authenticating-the-header-with-aad-v840).
652    pub fn create_aad(&self) -> Result<Vec<u8>> {
653        let tag = self.get_tag();
654        match self.header_type.version {
655            HeaderVersion::V1 => Err(anyhow::anyhow!(
656                "Serializing V1 headers has been deprecated"
657            )),
658            HeaderVersion::V2 => Err(anyhow::anyhow!(
659                "Serializing V2 headers has been deprecated"
660            )),
661            HeaderVersion::V3 => Ok(self.serialize_v3(&tag)),
662            HeaderVersion::V4 => {
663                let padding =
664                    vec![
665                        0u8;
666                        26 - get_nonce_len(&self.header_type.algorithm, &self.header_type.mode)
667                    ];
668                let master_key_nonce_len =
669                    get_nonce_len(&self.header_type.algorithm, &Mode::MemoryMode);
670                let padding2 = vec![0u8; 32 - master_key_nonce_len];
671                let mut header_bytes = Vec::<u8>::new();
672                header_bytes.extend_from_slice(&tag.version);
673                header_bytes.extend_from_slice(&tag.algorithm);
674                header_bytes.extend_from_slice(&tag.mode);
675                header_bytes.extend_from_slice(
676                    &self.salt.unwrap_or(
677                        self.keyslots.as_ref().ok_or_else(|| {
678                            anyhow::anyhow!("Cannot find a salt within the keyslot/header.")
679                        })?[0]
680                            .salt,
681                    ),
682                );
683                header_bytes.extend_from_slice(&self.nonce);
684                header_bytes.extend_from_slice(&padding);
685                header_bytes.extend_from_slice(&padding2);
686                Ok(header_bytes)
687            }
688            HeaderVersion::V5 => {
689                let mut header_bytes = Vec::<u8>::new();
690                header_bytes.extend_from_slice(&tag.version);
691                header_bytes.extend_from_slice(&tag.algorithm);
692                header_bytes.extend_from_slice(&tag.mode);
693                header_bytes.extend_from_slice(&self.nonce);
694                header_bytes.extend_from_slice(&vec![
695                    0u8;
696                    26 - get_nonce_len(
697                        &self.header_type.algorithm,
698                        &self.header_type.mode
699                    )
700                ]);
701                Ok(header_bytes)
702            }
703        }
704    }
705
706    /// This is a convenience function for writing a header to a writer
707    ///
708    /// # Examples
709    ///
710    /// ```rust,ignore
711    /// let mut output_file = File::create("test").unwrap();
712    ///
713    /// header.write(&mut output_file).unwrap();
714    /// ```
715    ///
716    pub fn write(&self, writer: &mut impl Write) -> Result<()> {
717        let header_bytes = self.serialize()?;
718        writer
719            .write(&header_bytes)
720            .context("Unable to write header")?;
721
722        Ok(())
723    }
724}