Skip to content

Commit 7d75de4

Browse files
committed
test: re-enable large file roundtrip tests and kdbx4 tests
1 parent c14bf19 commit 7d75de4

File tree

4 files changed

+249
-258
lines changed

4 files changed

+249
-258
lines changed

src/db/types/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,10 @@ impl Database {
112112
self.group_mut(recyclebin_id)
113113
}
114114

115+
pub fn num_attachments(&self) -> usize {
116+
self.attachments.len()
117+
}
118+
115119
pub fn num_entries(&self) -> usize {
116120
self.entries.len()
117121
}

src/format/kdbx4/mod.rs

Lines changed: 178 additions & 183 deletions
Original file line numberDiff line numberDiff line change
@@ -58,186 +58,181 @@ struct KDBX4InnerHeader {
5858
inner_random_stream_key: Vec<u8>,
5959
}
6060

61-
//#[cfg(feature = "save_kdbx4")]
62-
//#[cfg(test)]
63-
//mod kdbx4_tests {
64-
// use super::*;
65-
//
66-
// use crate::format::kdbx4::dump::dump_kdbx4;
67-
// use crate::{
68-
// config::{CompressionConfig, DatabaseConfig, InnerCipherConfig, KdfConfig, OuterCipherConfig},
69-
// db::{Database, Entry, Group, HeaderAttachment, NodeRef, Value},
70-
// format::KDBX4_CURRENT_MINOR_VERSION,
71-
// key::DatabaseKey,
72-
// };
73-
//
74-
// #[cfg(feature = "challenge_response")]
75-
// #[test]
76-
// fn test_with_challenge_response() {
77-
// let mut db = Database::new(DatabaseConfig::default());
78-
//
79-
// let mut root_group = Group::new("Root");
80-
// root_group.add_child(Entry::new());
81-
// root_group.add_child(Entry::new());
82-
// root_group.add_child(Entry::new());
83-
// db.root = root_group;
84-
//
85-
// let mut password_bytes: Vec<u8> = vec![];
86-
// let mut password: String = "".to_string();
87-
// password_bytes.resize(40, 0);
88-
// getrandom::fill(&mut password_bytes).unwrap();
89-
// for random_char in password_bytes {
90-
// password += &std::char::from_u32(random_char as u32).unwrap().to_string();
91-
// }
92-
//
93-
// let db_key = DatabaseKey::new()
94-
// .with_password(&password)
95-
// .with_challenge_response_key(crate::key::ChallengeResponseKey::LocalChallenge(
96-
// "0102030405060708090a0b0c0d0e0f1011121314".to_string(),
97-
// ));
98-
//
99-
// let mut encrypted_db = Vec::new();
100-
// dump_kdbx4(&db, &db_key, &mut encrypted_db).unwrap();
101-
//
102-
// let decrypted_db = parse_kdbx4(&encrypted_db, &db_key).unwrap();
103-
//
104-
// assert_eq!(decrypted_db.root.children.len(), 3);
105-
// }
106-
//
107-
// fn test_with_config(config: DatabaseConfig) {
108-
// let mut db = Database::new(config);
109-
//
110-
// let mut root_group = Group::new("Root");
111-
//
112-
// let mut entry_with_password = Entry::new();
113-
// entry_with_password
114-
// .fields
115-
// .insert("Title".to_string(), Value::Unprotected("Demo Entry".into()));
116-
//
117-
// entry_with_password
118-
// .fields
119-
// .insert("Password".to_string(), Value::Protected("secret".into()));
120-
//
121-
// root_group.add_child(entry_with_password);
122-
// root_group.add_child(Entry::new());
123-
// root_group.add_child(Entry::new());
124-
// db.root = root_group;
125-
//
126-
// let mut password_bytes: Vec<u8> = vec![];
127-
// let mut password: String = "".to_string();
128-
// password_bytes.resize(40, 0);
129-
// getrandom::fill(&mut password_bytes).unwrap();
130-
// for random_char in password_bytes {
131-
// password += &std::char::from_u32(random_char as u32).unwrap().to_string();
132-
// }
133-
//
134-
// let db_key = DatabaseKey::new().with_password(&password);
135-
//
136-
// let mut encrypted_db = Vec::new();
137-
// dump_kdbx4(&db, &db_key, &mut encrypted_db).unwrap();
138-
//
139-
// let decrypted_db = parse_kdbx4(&encrypted_db, &db_key).unwrap();
140-
//
141-
// assert_eq!(decrypted_db.root.children.len(), 3);
142-
//
143-
// if let Some(NodeRef::Entry(e)) = decrypted_db.root.get(&["Demo Entry"]) {
144-
// assert_eq!(e.get_password(), Some("secret"));
145-
// } else {
146-
// panic!("Could not get NodeRef")
147-
// }
148-
// }
149-
//
150-
// #[test]
151-
// pub fn test_config_matrix() {
152-
// let outer_cipher_configs = [
153-
// OuterCipherConfig::AES256,
154-
// OuterCipherConfig::Twofish,
155-
// OuterCipherConfig::ChaCha20,
156-
// ];
157-
//
158-
// let compression_configs = [CompressionConfig::None, CompressionConfig::GZip];
159-
//
160-
// let inner_cipher_configs = [
161-
// InnerCipherConfig::Plain,
162-
// InnerCipherConfig::Salsa20,
163-
// InnerCipherConfig::ChaCha20,
164-
// ];
165-
//
166-
// let kdf_configs = [
167-
// KdfConfig::Aes { rounds: 10 },
168-
// KdfConfig::Argon2 {
169-
// iterations: 10,
170-
// memory: 65536,
171-
// parallelism: 2,
172-
// version: argon2::Version::Version13,
173-
// },
174-
// KdfConfig::Argon2id {
175-
// iterations: 10,
176-
// memory: 65536,
177-
// parallelism: 2,
178-
// version: argon2::Version::Version13,
179-
// },
180-
// ];
181-
//
182-
// for outer_cipher_config in &outer_cipher_configs {
183-
// for compression_config in &compression_configs {
184-
// for inner_cipher_config in &inner_cipher_configs {
185-
// for kdf_config in &kdf_configs {
186-
// let config = DatabaseConfig {
187-
// version: DatabaseVersion::KDB4(KDBX4_CURRENT_MINOR_VERSION),
188-
// outer_cipher_config: outer_cipher_config.clone(),
189-
// compression_config: compression_config.clone(),
190-
// inner_cipher_config: inner_cipher_config.clone(),
191-
// kdf_config: kdf_config.clone(),
192-
// public_custom_data: Default::default(),
193-
// };
194-
//
195-
// println!("Testing with config: {config:?}");
196-
//
197-
// test_with_config(config);
198-
// }
199-
// }
200-
// }
201-
// }
202-
// }
203-
//
204-
// #[test]
205-
// pub fn header_attachments() {
206-
// let mut root_group = Group::new("Root");
207-
// root_group.add_child(Entry::new());
208-
//
209-
// let mut db = Database::new(DatabaseConfig::default());
210-
//
211-
// db.header_attachments = vec![
212-
// HeaderAttachment {
213-
// flags: 1,
214-
// content: vec![0x01, 0x02, 0x03, 0x04],
215-
// },
216-
// HeaderAttachment {
217-
// flags: 2,
218-
// content: vec![0x04, 0x03, 0x02, 0x01],
219-
// },
220-
// ];
221-
//
222-
// let mut entry = Entry::new();
223-
// entry
224-
// .fields
225-
// .insert("Title".to_string(), Value::Unprotected("Demo entry".to_string()));
226-
//
227-
// db.root.add_child(entry);
228-
//
229-
// let db_key = DatabaseKey::new().with_password("test");
230-
//
231-
// let mut encrypted_db = Vec::new();
232-
// dump_kdbx4(&db, &db_key, &mut encrypted_db).unwrap();
233-
//
234-
// let decrypted_db = parse_kdbx4(&encrypted_db, &db_key).unwrap();
235-
//
236-
// assert_eq!(decrypted_db.root.children.len(), 1);
237-
//
238-
// let header_attachments = &decrypted_db.header_attachments;
239-
// assert_eq!(header_attachments.len(), 2);
240-
// assert_eq!(header_attachments[0].flags, 1);
241-
// assert_eq!(header_attachments[0].content, [0x01, 0x02, 0x03, 0x04]);
242-
// }
243-
//}
61+
#[cfg(feature = "save_kdbx4")]
62+
#[cfg(test)]
63+
mod kdbx4_tests {
64+
use super::*;
65+
66+
use crate::db::fields;
67+
use crate::format::kdbx4::dump::dump_kdbx4;
68+
use crate::{
69+
config::{CompressionConfig, DatabaseConfig, InnerCipherConfig, KdfConfig, OuterCipherConfig},
70+
db::{Database, Entry, Group, Value},
71+
format::KDBX4_CURRENT_MINOR_VERSION,
72+
key::DatabaseKey,
73+
};
74+
75+
#[cfg(feature = "challenge_response")]
76+
#[test]
77+
fn test_with_challenge_response() {
78+
let mut db = Database::new();
79+
80+
let mut root = db.root_mut();
81+
root.add_entry();
82+
root.add_entry();
83+
root.add_entry();
84+
85+
let mut password_bytes: Vec<u8> = vec![];
86+
let mut password: String = "".to_string();
87+
password_bytes.resize(40, 0);
88+
getrandom::fill(&mut password_bytes).unwrap();
89+
for random_char in password_bytes {
90+
password += &std::char::from_u32(random_char as u32).unwrap().to_string();
91+
}
92+
93+
let db_key = DatabaseKey::new()
94+
.with_password(&password)
95+
.with_challenge_response_key(crate::key::ChallengeResponseKey::LocalChallenge(
96+
"0102030405060708090a0b0c0d0e0f1011121314".to_string(),
97+
));
98+
99+
let mut encrypted_db = Vec::new();
100+
dump_kdbx4(&db, &db_key, &mut encrypted_db).unwrap();
101+
102+
let decrypted_db = parse_kdbx4(&encrypted_db, &db_key).unwrap();
103+
104+
assert_eq!(decrypted_db.num_entries(), 3);
105+
}
106+
107+
fn test_with_config(config: DatabaseConfig) {
108+
let mut db = Database::new();
109+
db.config = config;
110+
111+
let mut root = db.root_mut();
112+
113+
let mut entry_with_password = root.add_entry();
114+
entry_with_password.set_unprotected(fields::TITLE, "Demo Entry");
115+
entry_with_password.set_protected(fields::PASSWORD, "secret");
116+
117+
root.add_entry();
118+
root.add_entry();
119+
120+
let mut password_bytes: Vec<u8> = vec![];
121+
let mut password: String = "".to_string();
122+
password_bytes.resize(40, 0);
123+
getrandom::fill(&mut password_bytes).unwrap();
124+
for random_char in password_bytes {
125+
password += &std::char::from_u32(random_char as u32).unwrap().to_string();
126+
}
127+
128+
let db_key = DatabaseKey::new().with_password(&password);
129+
130+
let mut encrypted_db = Vec::new();
131+
dump_kdbx4(&db, &db_key, &mut encrypted_db).unwrap();
132+
133+
let decrypted_db = parse_kdbx4(&encrypted_db, &db_key).unwrap();
134+
135+
assert_eq!(decrypted_db.num_entries(), 3);
136+
137+
let decrypted_root = decrypted_db.root();
138+
let the_entry = decrypted_root
139+
.entry_by_name("Demo Entry")
140+
.expect("Could not find entry");
141+
142+
assert_eq!(the_entry.get_str(fields::PASSWORD), Some("secret"));
143+
}
144+
145+
#[test]
146+
pub fn test_config_matrix() {
147+
let outer_cipher_configs = [
148+
OuterCipherConfig::AES256,
149+
OuterCipherConfig::Twofish,
150+
OuterCipherConfig::ChaCha20,
151+
];
152+
153+
let compression_configs = [CompressionConfig::None, CompressionConfig::GZip];
154+
155+
let inner_cipher_configs = [
156+
InnerCipherConfig::Plain,
157+
InnerCipherConfig::Salsa20,
158+
InnerCipherConfig::ChaCha20,
159+
];
160+
161+
let kdf_configs = [
162+
KdfConfig::Aes { rounds: 10 },
163+
KdfConfig::Argon2 {
164+
iterations: 10,
165+
memory: 65536,
166+
parallelism: 2,
167+
version: argon2::Version::Version13,
168+
},
169+
KdfConfig::Argon2id {
170+
iterations: 10,
171+
memory: 65536,
172+
parallelism: 2,
173+
version: argon2::Version::Version13,
174+
},
175+
];
176+
177+
for outer_cipher_config in &outer_cipher_configs {
178+
for compression_config in &compression_configs {
179+
for inner_cipher_config in &inner_cipher_configs {
180+
for kdf_config in &kdf_configs {
181+
let config = DatabaseConfig {
182+
version: DatabaseVersion::KDB4(KDBX4_CURRENT_MINOR_VERSION),
183+
outer_cipher_config: outer_cipher_config.clone(),
184+
compression_config: compression_config.clone(),
185+
inner_cipher_config: inner_cipher_config.clone(),
186+
kdf_config: kdf_config.clone(),
187+
public_custom_data: Default::default(),
188+
};
189+
190+
println!("Testing with config: {config:?}");
191+
192+
test_with_config(config);
193+
}
194+
}
195+
}
196+
}
197+
}
198+
199+
#[test]
200+
pub fn header_attachments() {
201+
let mut db = Database::new();
202+
203+
let mut root = db.root_mut();
204+
205+
let mut entry = root.add_entry();
206+
entry.set_unprotected(fields::TITLE, "Demo entry");
207+
entry.set_protected(fields::PASSWORD, "secret");
208+
209+
let mut attachment1 = entry.add_attachment();
210+
attachment1.name = "hello.txt".to_string();
211+
attachment1.set_data(b"Hello, World!".to_vec());
212+
213+
let mut attachment2 = entry.add_attachment();
214+
attachment2.name = "image.png".to_string();
215+
attachment2.set_data(vec![0x89, 0x50, 0x4E, 0x47]);
216+
217+
let db_key = DatabaseKey::new().with_password("test");
218+
219+
let mut encrypted_db = Vec::new();
220+
dump_kdbx4(&db, &db_key, &mut encrypted_db).unwrap();
221+
222+
let decrypted_db = parse_kdbx4(&encrypted_db, &db_key).unwrap();
223+
224+
assert_eq!(decrypted_db.num_entries(), 1);
225+
assert_eq!(decrypted_db.num_attachments(), 2);
226+
227+
let decrypted_root = decrypted_db.root();
228+
let the_entry = decrypted_root
229+
.entry_by_name("Demo entry")
230+
.expect("Could not find entry");
231+
232+
the_entry.attachments().for_each(|a| match a.name.as_str() {
233+
"hello.txt" => assert_eq!(a.data(), &b"Hello, World!"[..]),
234+
"image.png" => assert_eq!(a.data(), &[0x89, 0x50, 0x4E, 0x47][..]),
235+
_ => panic!("Unexpected attachment name"),
236+
});
237+
}
238+
}

tests/file_read_tests.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
mod file_read_tests {
22

33
use anyhow::Result;
4-
use keepass::{
5-
db::{Database, GroupId},
6-
DatabaseKey,
7-
};
4+
use keepass::{db::Database, DatabaseKey};
85
use uuid::uuid;
96

107
use std::{fs::File, path::Path};

0 commit comments

Comments
 (0)