Skip to main content

volaris_crypto/
header.rs

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