@@ -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+ }
0 commit comments