Skip to main content

crypt_config/config/
cipher_loader.rs

1extern 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}