loom_types_entities/
keystore.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
use aes::cipher::{Block, BlockDecrypt, KeyInit};
use aes::Aes128;
use eyre::{ErrReport, Result};
use sha2::{Digest, Sha512};

use crate::private::KEY_ENCRYPTION_PWD;

const BLOCK_SIZE: usize = 16;

#[derive(Clone, Default)]
pub struct KeyStore {
    pwd: Vec<u8>,
}

impl KeyStore {
    pub fn new() -> KeyStore {
        KeyStore { pwd: KEY_ENCRYPTION_PWD.to_vec() }
    }

    pub fn new_from_string(pwd: String) -> KeyStore {
        KeyStore { pwd: pwd.as_bytes().to_vec() }
    }
    pub fn new_from_bytes(pwd: Vec<u8>) -> KeyStore {
        KeyStore { pwd }
    }

    pub fn encrypt_once(&self, data: &[u8]) -> Result<Vec<u8>> {
        if self.pwd.is_empty() {
            return Err(ErrReport::msg("NOT_INITIALIZED"));
        }

        let mut hasher = Sha512::new();
        hasher.update(self.pwd.clone());
        let pwd_hash = hasher.finalize();

        let cipher = Aes128::new_from_slice(&pwd_hash[0..16]).unwrap();

        //println!("{:?}", pwd_hash);

        let mut ret = Vec::new();
        let mut block: Block<Aes128> = [0u8; BLOCK_SIZE].into();

        let mut a = 0;
        while a + BLOCK_SIZE <= data.len() {
            block.copy_from_slice(&data[a..a + BLOCK_SIZE]);
            cipher.decrypt_block(&mut block);
            ret.extend_from_slice(&block);
            a += BLOCK_SIZE;
        }

        let mut sha = Sha512::new();
        sha.update(&ret);
        let crc = &sha.finalize()[0..4];

        if &data[a..a + 4] != crc {
            return Err(ErrReport::msg("BAD_CHECKSUM"));
        }

        Ok(ret)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_encrypt_once_not_initialized() {
        let key_store = KeyStore::new_from_string(String::from(""));
        let data = vec![0u8; 36];

        match key_store.encrypt_once(&data) {
            Ok(_) => panic!("Expected an error, but didn't get one"),
            Err(e) => assert_eq!(format!("{}", e), "NOT_INITIALIZED"),
        }
    }

    #[test]
    fn test_encrypt_once_bad_checksum() {
        let key_store = KeyStore::new_from_string(String::from("password"));
        let data = vec![0u8; 36];

        match key_store.encrypt_once(&data) {
            Ok(_) => panic!("Expected an error, but didn't get one"),
            Err(e) => assert_eq!(format!("{}", e), "BAD_CHECKSUM"),
        }
    }

    // For this test, you'll need some valid encrypted data to pass and a correct password.
    #[test]
    fn test_encrypt_once_valid_data() {
        let key: Vec<u8> = vec![0x41, 0x8f, 0x2, 0xe4, 0x7e, 0xe4, 0x6, 0xaa, 0xee, 0x71, 0x9e, 0x30, 0xea, 0xe6, 0x64, 0x23];
        let key_store = KeyStore::new_from_bytes(key);
        //let encrypted_data = vec![0u8;36]; // Provide valid encrypted data here

        let encrypted_data = hex::decode("51d9dc302b02a02a94d3c7f3057549cd0c990f4c7cc822b61af584fb85afdf209084f48a").unwrap();

        match key_store.encrypt_once(&encrypted_data) {
            Ok(decrypted_data) => {
                println!("{}", hex::encode(decrypted_data));
            }
            Err(_) => {
                //println!("{}", hex::encode(decrypted_data));
                panic!("BAD_CHECKSUM")
            }
        }
    }
}