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
|
//!
use miscreant::aead::{Aes256Siv, Algorithm};
use security::{encoding, random, keys::{Key, KEY_LENGTH}};
use serde::{Serialize, de::DeserializeOwned};
use serde_json;
use std::error::Error;
/// The main encryption context
pub struct CryptoEngine {
ctx: Aes256Siv,
key: Key,
iv: Vec<u8>,
}
/// Represents some packed data – includes nonce and blob
#[derive(Serialize, Deserialize)]
struct PackedData {
nonce: Vec<u8>,
data: Vec<u8>,
}
impl CryptoEngine {
/// Create a new encryption context with a key
pub fn new(key: Key) -> CryptoEngine {
return CryptoEngine {
ctx: Aes256Siv::new(&key.to_slice()),
key: key,
iv: random::bytes(KEY_LENGTH),
};
}
/// Load an existing encryption context into scope
pub fn load(key: Key, iv: Vec<u8>) -> CryptoEngine {
return CryptoEngine {
ctx: Aes256Siv::new(&key.to_slice()),
key: key,
iv: iv,
};
}
/// Encrypt a piece of data, returns a packed and encoded string
pub fn encrypt<T: Serialize>(&mut self, data: &T) -> Result<String, Box<Error>> {
let serial = serde_json::to_string(&data)?;
let nonce = random::bytes(64);
let iv = &self.iv.as_slice();
let data = &serial.as_bytes();
let encrypted = self.ctx.seal(nonce.as_slice(), iv, data);
let packed = PackedData {
nonce: nonce,
data: encrypted,
};
let enc_packed = serde_json::to_string(&packed)?;
return Ok(encoding::base64_encode(&enc_packed.into_bytes()));
}
/// Decrypt a ciphertext string into a type object
pub fn decrypt<T: DeserializeOwned>(&mut self, cipher: String) -> Result<T, Box<Error>> {
let dec_packed = String::from_utf8(encoding::base64_decode(&cipher))?;
let p: PackedData = serde_json::from_str(&dec_packed)?;
let iv = &self.iv.as_slice();
let decrypted = self.ctx.open(p.nonce.as_slice(), iv, p.data.as_slice())?;
let decr_str = String::from_utf8(decrypted)?;
let t: T = serde_json::from_str(&decr_str)?;
return Ok(t);
}
}
|