use aes_gcm::{ aead::{Aead, AeadCore, KeyInit, OsRng}, Aes256Gcm, Key, Nonce }; use std::io; static PASSWORD_TEST: &str = "MyPasswordStorage"; // will be added with nonce for storing each time pub struct Encoder { // will be stored with padding 32 bytes passphrase: String } impl Encoder { pub fn from(passphrase: &String) -> Encoder { // TODO: throw error if password longer that 32 bytes let padded_passphrase = Encoder::get_passhrase_with_padding(passphrase); Encoder { passphrase: padded_passphrase } } fn get_passhrase_with_padding(passphrase: &String) -> String { let mut result = passphrase.clone(); while result.len() < 32 { // use '-' for padding, can be anything else result.push('-'); } result } // TODO: error type pub fn encrypt(&self, plain_text: &String) -> String { let key = Key::::from_slice(self.passphrase.as_bytes()); let nonce = Aes256Gcm::generate_nonce(&mut OsRng); let cipher = Aes256Gcm::new(key); // TODO: mar error inted of expect let ciphered_data = cipher.encrypt(&nonce, plain_text.as_bytes()) .expect("failed to encrypt"); // combining nonce and encrypted data together // for storage purpose let mut encrypted_data: Vec = nonce.to_vec(); encrypted_data.extend_from_slice(&ciphered_data); hex::encode(encrypted_data) } // TODO: review error type pub fn decrypt(&self, encrypted_data: String) -> io::Result { let encrypted_data = hex::decode(encrypted_data) .expect("failed to decode hex string into vec"); let key = Key::::from_slice(self.passphrase.as_bytes()); let (nonce_arr, ciphered_data) = encrypted_data.split_at(12); let nonce = Nonce::from_slice(nonce_arr); let cipher = Aes256Gcm::new(key); let plaintext = cipher.decrypt(nonce, ciphered_data) .expect("failed to decrypt data"); let result = String::from_utf8(plaintext) .expect("failed to convert vector of bytes to string"); //.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; //match String::from_utf8(content) { // Ok(s) => Ok(s), // Err(e) => Err(io::Error::new(io::ErrorKind::InvalidData, e)) //} Ok(result) } pub fn test_encoded_passphrase(&self, passphrase_encrypted: String) -> io::Result { let decrypted = self.decrypt(passphrase_encrypted)?; Ok(PASSWORD_TEST == decrypted) } pub fn get_encoded_test_passphrase(&self) -> String { self.encrypt(&PASSWORD_TEST.to_string()) } }