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}