crypt_config/config/
cipher_loader.rs1extern crate serde;
2extern crate serde_json;
3
4use std::collections::HashMap;
5
6use serde::{Deserialize, Serialize};
7
8use crate::config::{CipherConfig, CipherData, Config};
9use crate::error::{CryptError, CryptResult};
10
11#[derive(Serialize, Deserialize)]
12struct Cfg {
13 algorithm: String,
14 secret: String
15}
16
17#[derive(Serialize, Deserialize)]
18struct Cipher {
19 configurations: HashMap<String, Cfg>
20}
21
22#[derive(Serialize, Deserialize)]
23struct Ciphers {
24 ciphers: HashMap<String, Cipher>
25}
26
27#[allow(dead_code)]
28type CipherLoader = fn(&mut Config, &str) -> CryptResult<()>;
29
30#[allow(dead_code)]
31pub fn get_cipher_loader(version: &str) -> CipherLoader {
32 if version.starts_with("1.0") {
33 cipher_loader_1_0
34 } else {
35 cipher_loader_unknown
36 }
37}
38
39#[allow(dead_code)]
40fn cipher_loader_unknown(_config: &mut Config, _data: &str) -> CryptResult<()> {
41 Err(CryptError::UnsupportedConfigVersion())
42}
43
44#[allow(dead_code)]
45fn cipher_loader_1_0(config: &mut Config, data: &str) -> CryptResult<()> {
46 let ciphers: Ciphers = serde_json::from_str(data)?;
47
48 for (field, cipher) in ciphers.ciphers {
49 if !config.is_cipher_exist(&field) {
50 config.insert_cipher(field.clone(), Box::new(CipherData::new()));
51 }
52
53 for (version, cfg) in cipher.configurations {
54 if config.is_cipher_version_exist(&field, &version) {
55 return Err(CryptError::DuplicationCipherConfigVersion(version));
56 }
57
58 is_algorithm_supported(&cfg.algorithm)?;
59
60 let secret = base64::decode(&cfg.secret)?;
61
62 config.add_cipher_version(&field, &version, Box::new(CipherConfig::new(cfg.algorithm, secret)));
63 }
64 }
65
66 Ok(())
67}
68
69fn is_algorithm_supported(algorithm: &str) -> CryptResult<()> {
70 match algorithm {
71 "aes_cbc" => Ok(()),
72 "aes_cfb1" => Ok(()),
73 "aes_ecb" => Ok(()),
74 _ => Err(CryptError::UnsupportedCipherAlgorithm(algorithm.to_string()))
75 }
76}
77
78#[cfg(test)]
79mod tests {
80 use std::fs;
81 use std::path::PathBuf;
82
83 use crate::config::get_config_version;
84 use crate::config::Config;
85
86 use super::get_cipher_loader;
87
88 fn get_test_data_path(fname: &str) -> PathBuf {
89 let mut path = PathBuf::from(file!());
90 path.pop();
91 path.pop();
92 path.pop();
93 path.pop();
94 path.push("test_data");
95 path.push(fname);
96 path
97 }
98
99 #[test]
100 fn load_configuration() {
101 let mut config = Config::new();
102
103 let path = get_test_data_path("config.json");
104 let content = fs::read_to_string(path).unwrap();
105
106 let version = get_config_version(&content).unwrap();
107 let cipher_loader = get_cipher_loader(&version);
108
109 cipher_loader(&mut config, &content).unwrap();
110
111 assert!(config.is_cipher_exist("email"));
112 assert_eq!("2.1", config.get_cipher_latest_version("email"));
113 assert!(config.is_cipher_version_exist("email", "1.0"));
114 assert!(config.is_cipher_version_exist("email", "1.1"));
115 assert!(config.is_cipher_version_exist("email", "2.1"));
116 }
117}