shadow_crypt_core/v1/
header.rs1use crate::v1::key::KeyDerivationParams;
2
3#[derive(Debug, Clone)]
5pub struct FileHeader {
6 pub magic: [u8; 6], pub version: u8, pub header_length: u32, pub salt: [u8; 16], pub kdf_memory: u32, pub kdf_iterations: u32, pub kdf_parallelism: u32, pub kdf_key_length: u8, pub content_nonce: [u8; 24], pub filename_nonce: [u8; 24], pub filename_ciphertext_length: u16, pub filename_ciphertext: Vec<u8>, }
19
20impl FileHeader {
21 pub fn new(
22 salt: [u8; 16],
23 kdf_params: KeyDerivationParams,
24 content_nonce: [u8; 24],
25 filename_nonce: [u8; 24],
26 filename_ciphertext: Vec<u8>,
27 ) -> Self {
28 let filename_ciphertext_length = filename_ciphertext.len() as u16;
29 let size = Self::min_length() + filename_ciphertext.len();
30
31 FileHeader {
32 magic: *b"SHADOW",
33 version: 1,
34 header_length: size as u32,
35 salt,
36 kdf_memory: kdf_params.memory_cost,
37 kdf_iterations: kdf_params.time_cost,
38 kdf_parallelism: kdf_params.parallelism,
39 kdf_key_length: kdf_params.key_size,
40 content_nonce,
41 filename_nonce,
42 filename_ciphertext_length,
43 filename_ciphertext,
44 }
45 }
46
47 pub fn min_length() -> usize {
49 90 }
51}
52
53#[cfg(test)]
54mod tests {
55 use crate::profile;
56
57 use super::*;
58
59 fn get_test_params() -> KeyDerivationParams {
60 let profile = profile::SecurityProfile::Test;
61 KeyDerivationParams::from(profile)
62 }
63
64 #[test]
65 fn default_values_are_correct() {
66 let header = FileHeader::new(
67 [0u8; 16],
68 get_test_params(),
69 [0u8; 24],
70 [0u8; 24],
71 vec![1, 2, 3, 4],
72 );
73
74 assert_eq!(&header.magic, b"SHADOW");
75 assert_eq!(header.version, 1);
76 }
77
78 #[test]
79 fn header_size_is_calculated_correctly() {
80 let filename_ciphertext = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
81 let header = FileHeader::new(
82 [0u8; 16],
83 get_test_params(),
84 [0u8; 24],
85 [0u8; 24],
86 filename_ciphertext.clone(),
87 );
88
89 let expected_size: u32 = 90 + filename_ciphertext.len() as u32;
90
91 assert_eq!(header.header_length, expected_size);
92 }
93}