use crate::error::IoTError;
use serde::{self, Deserialize, Serialize};
use ecies::{FULL_PUBLIC_KEY_SIZE, encrypt, };
const NO_ENCRYPTION: &str = "NO ENCRYPTION";
const ECIES_SECP256K1: &str = "ECIES-secp256k1";
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
pub enum DataEncryptionMethod {
NoEncryption,
EciesSecp256k1,
}
impl std::fmt::Display for DataEncryptionMethod {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
DataEncryptionMethod::NoEncryption => write!(f, "{}", NO_ENCRYPTION),
DataEncryptionMethod::EciesSecp256k1 => write!(f, "{}", ECIES_SECP256K1),
}
}
}
impl std::str::FromStr for DataEncryptionMethod {
type Err = IoTError;
fn from_str(s: &str) -> ::core::result::Result<Self, Self::Err> {
match s {
NO_ENCRYPTION => {
::core::result::Result::Ok(DataEncryptionMethod::NoEncryption)
}
ECIES_SECP256K1 => {
::core::result::Result::Ok(DataEncryptionMethod::EciesSecp256k1)
}
_ => ::core::result::Result::Err(IoTError::IotStatusParsingError),
}
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct DataEncryptionConfig {
pub method: DataEncryptionMethod,
pub public_key: Vec<u8>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct DataEncryptionConfigOption {
pub method: Option<DataEncryptionMethod>,
pub public_key: Option<Vec<u8>>,
}
impl Default for DataEncryptionConfig {
fn default() -> DataEncryptionConfig {
DataEncryptionConfig {
method: DataEncryptionMethod::NoEncryption,
public_key: Vec::with_capacity(FULL_PUBLIC_KEY_SIZE),
}
}
}
impl DataEncryptionConfig {
pub fn new() -> DataEncryptionConfig {
Default::default()
}
pub fn set_public_key(&mut self, public_key: Vec<u8>) {
self.public_key = public_key;
}
pub fn get_public_key(&self) -> &Vec<u8> {
&self.public_key
}
pub fn update(&mut self, data_encryption_config_option: &DataEncryptionConfigOption) {
if let Some(x) = &data_encryption_config_option.method {
self.method = x.clone();
}
if let Some(x) = &data_encryption_config_option.public_key {
self.public_key = x.to_vec();
}
}
pub fn encrypt_b64(&self, plaintext: String) -> Result<String, IoTError> {
let public_key = self.get_public_key();
let ciphertext = encrypt(public_key, plaintext.as_bytes())?;
return Ok(base64::encode_config(&ciphertext, base64::STANDARD));
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn update_test() {
println!("\nTEST PART 1");
let data = r#"
{
"data_encryption_config": {
"method": "EciesSecp256k1",
"public_key": [
4,89,117,155,81,243,172,179,
90,195,137,53,151,179,94,29,
83,81,109,41,239,43,231,104,
14,189,163,2,229,86,3,148,
164,194,250,198,166,60,62,162,
124,188,178,137,87,61,52,245,
18,210,207,175,130,234,120,161,
45,205,156,7,34,37,164,106,
128
]
}
}"#;
let mut dec = DataEncryptionConfig::new();
println!("DataEncryptionConfig - NEW: {:?}", dec);
let val: Value = serde_json::from_str(data).unwrap();
let val: serde_json::Value = val["data_encryption_config"].clone();
let deco: DataEncryptionConfigOption = serde_json::from_value(val).unwrap();
println!("DataEncryptionConfig - OPTION: {:?}", deco);
dec.update(&deco);
println!("DataEncryptionConfig - UPDATED: {:?}", dec);
assert_eq!(dec.method, DataEncryptionMethod::EciesSecp256k1);
assert_eq!(dec.public_key.len(), 65);
assert_eq!(dec.public_key.capacity(), 65);
assert_eq!(dec.public_key[0], 4u8);
assert_eq!(dec.public_key[64], 128u8);
println!("\nTEST PART 2");
let data = r#"
{
"data_encryption_config": {
"method": "NoEncryption"
}
}"#;
let mut dec = DataEncryptionConfig::new();
println!("DataEncryptionConfig - NEW: {:?}", dec);
let val: Value = serde_json::from_str(data).unwrap();
let val: serde_json::Value = val["data_encryption_config"].clone();
let deco: DataEncryptionConfigOption = serde_json::from_value(val).unwrap();
println!("DataEncryptionConfig - OPTION: {:?}", deco);
dec.update(&deco);
println!("DataEncryptionConfig - UPDATED: {:?}", dec);
assert_eq!(dec.method, DataEncryptionMethod::NoEncryption);
assert_eq!(dec.public_key.len(), 0);
assert_eq!(dec.public_key.capacity(), 65);
}
use ecies::{decrypt};
use serde_json::Value;
#[test]
fn encrypt_b64_test() {
let public_key: Vec<u8> = vec![
4u8,89u8,117u8,155u8,81u8,243u8,172u8,179u8,
90u8,195u8,137u8,53u8,151u8,179u8,94u8,29u8,
83u8,81u8,109u8,41u8,239u8,43u8,231u8,104u8,
14u8,189u8,163u8,2u8,229u8,86u8,3u8,148u8,
164u8,194u8,250u8,198u8,166u8,60u8,62u8,162u8,
124u8,188u8,178u8,137u8,87u8,61u8,52u8,245u8,
18u8,210u8,207u8,175u8,130u8,234u8,120u8,161u8,
45u8,205u8,156u8,7u8,34u8,37u8,164u8,106u8,
128u8
];
let secret_key: Vec<u8> = vec![
209, 69, 249, 227, 132, 172, 11, 253,
70, 42, 122, 86, 14, 10, 141, 99,
31, 156, 13, 179, 38, 112, 240, 242,
141, 211, 124, 250, 74, 47, 242, 195
];
let plaintext = "Hello World";
let mut data_encr_config = DataEncryptionConfig::new();
data_encr_config.set_public_key(public_key);
let ciphertext = data_encr_config.encrypt_b64(plaintext.to_string()).unwrap();
let ciphertext = base64::decode_config(ciphertext, base64::STANDARD).unwrap();
let decrypted_text = decrypt(&secret_key, &ciphertext).unwrap();
assert_eq!(plaintext.as_bytes(), decrypted_text);
}
}