kpdb/types/key_file.rs
1// Copyright (c) 2016-2017 Martijn Rijkeboer <[email protected]>
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9use super::key_file_type::KeyFileType;
10use super::result::Result;
11use crate::crypto::random_gen::RandomGen;
12use crate::format::{kf_reader, kf_writer};
13use secstr::SecStr;
14use std::io::{Read, Write};
15
16/// A key file used for encrypting and decrypting the database.
17#[derive(Clone, Debug, PartialEq)]
18pub struct KeyFile {
19 /// The key data.
20 pub key: SecStr,
21
22 /// The type of key file.
23 pub file_type: KeyFileType,
24}
25
26impl KeyFile {
27 /// An convenience alias for `KeyFile::new_xml()`.
28 pub fn new() -> Result<KeyFile> {
29 KeyFile::new_xml()
30 }
31
32 /// Attempts to create a new binary key file.
33 ///
34 /// # Examples
35 ///
36 /// ```rust
37 /// # use kpdb::Result;
38 /// use kpdb::KeyFile;
39 ///
40 /// # fn new_example() -> Result<()> {
41 /// let key = KeyFile::new_binary()?;
42 /// # Ok(())
43 /// # }
44 /// ```
45 pub fn new_binary() -> Result<KeyFile> {
46 let key = KeyFile::get_random_key()?;
47 Ok(KeyFile {
48 key: key,
49 file_type: KeyFileType::Binary,
50 })
51 }
52
53 /// Attempts to create a new hexadecimal key file.
54 ///
55 /// # Examples
56 ///
57 /// ```rust
58 /// # use kpdb::Result;
59 /// use kpdb::KeyFile;
60 ///
61 /// # fn new_example() -> Result<()> {
62 /// let key = KeyFile::new_hex()?;
63 /// # Ok(())
64 /// # }
65 /// ```
66 pub fn new_hex() -> Result<KeyFile> {
67 let key = KeyFile::get_random_key()?;
68 Ok(KeyFile {
69 key: key,
70 file_type: KeyFileType::Hex,
71 })
72 }
73
74 /// Attempts to create a new XML key file.
75 ///
76 /// # Examples
77 ///
78 /// ```rust
79 /// # use kpdb::Result;
80 /// use kpdb::KeyFile;
81 ///
82 /// # fn new_example() -> Result<()> {
83 /// let key = KeyFile::new_xml()?;
84 /// # Ok(())
85 /// # }
86 /// ```
87 pub fn new_xml() -> Result<KeyFile> {
88 let key = KeyFile::get_random_key()?;
89 Ok(KeyFile {
90 key: key,
91 file_type: KeyFileType::Xml,
92 })
93 }
94
95 /// Attempts to open a key file.
96 ///
97 /// # Examples
98 ///
99 /// ```rust,no_run
100 /// # use kpdb::Result;
101 /// use kpdb::KeyFile;
102 /// use std::fs::File;
103 ///
104 /// # fn open_example() -> Result<()> {
105 /// let mut file = File::open("passwords.key")?;
106 /// let key = KeyFile::open(&mut file)?;
107 /// # Ok(())
108 /// # }
109 /// ```
110 pub fn open<R: Read>(reader: &mut R) -> Result<KeyFile> {
111 kf_reader::read(reader)
112 }
113
114 /// Attempts to save the key file.
115 ///
116 /// # Examples
117 ///
118 /// ```rust,no_run
119 /// # use kpdb::Result;
120 /// use kpdb::KeyFile;
121 /// use std::fs::File;
122 ///
123 /// # fn save_example() -> Result<()> {
124 /// let key = KeyFile::new()?;
125 /// let mut file = File::create("new.key")?;
126 ///
127 /// key.save(&mut file)?;
128 /// # Ok(())
129 /// # }
130 /// ```
131 pub fn save<W: Write>(&self, writer: &mut W) -> Result<()> {
132 kf_writer::write(writer, self)
133 }
134
135 fn get_random_key() -> Result<SecStr> {
136 let mut random = RandomGen::new()?;
137 let bytes = random.next_32_bytes().to_vec();
138 Ok(SecStr::new(bytes))
139 }
140}
141
142#[cfg(test)]
143mod tests {
144
145 use super::*;
146 use crate::types::KeyFileType;
147
148 #[test]
149 fn test_new_returns_xml_instance() {
150 let target = KeyFile::new().unwrap();
151 assert_eq!(target.file_type, KeyFileType::Xml);
152 }
153
154 #[test]
155 fn test_new_binary_returns_correct_instance() {
156 let a = KeyFile::new_binary().unwrap();
157 let b = KeyFile::new_binary().unwrap();
158 assert!(a.key != b.key);
159 assert_eq!(a.file_type, KeyFileType::Binary);
160 assert_eq!(b.file_type, KeyFileType::Binary);
161 }
162
163 #[test]
164 fn test_new_hex_returns_correct_instance() {
165 let a = KeyFile::new_hex().unwrap();
166 let b = KeyFile::new_hex().unwrap();
167 assert!(a.key != b.key);
168 assert_eq!(a.file_type, KeyFileType::Hex);
169 assert_eq!(b.file_type, KeyFileType::Hex);
170 }
171
172 #[test]
173 fn test_new_xml_returns_correct_instance() {
174 let a = KeyFile::new_xml().unwrap();
175 let b = KeyFile::new_xml().unwrap();
176 assert!(a.key != b.key);
177 assert_eq!(a.file_type, KeyFileType::Xml);
178 assert_eq!(b.file_type, KeyFileType::Xml);
179 }
180}