From a21737e2b7f8d1e426726bdd7536033f299d476a Mon Sep 17 00:00:00 2001 From: Ellie Huxtable Date: Tue, 20 Apr 2021 21:53:07 +0100 Subject: Use cargo workspaces (#37) * Switch to Cargo workspaces Breaking things into "client", "server" and "common" makes managing the codebase much easier! client - anything running on a user's machine for adding history server - handles storing/syncing history and running a HTTP server common - request/response API definitions, common utils, etc * Update dockerfile --- src/local/encryption.rs | 108 ------------------------------------------------ 1 file changed, 108 deletions(-) delete mode 100644 src/local/encryption.rs (limited to 'src/local/encryption.rs') diff --git a/src/local/encryption.rs b/src/local/encryption.rs deleted file mode 100644 index 3c1699e3..00000000 --- a/src/local/encryption.rs +++ /dev/null @@ -1,108 +0,0 @@ -// The general idea is that we NEVER send cleartext history to the server -// This way the odds of anything private ending up where it should not are -// very low -// The server authenticates via the usual username and password. This has -// nothing to do with the encryption, and is purely authentication! The client -// generates its own secret key, and encrypts all shell history with libsodium's -// secretbox. The data is then sent to the server, where it is stored. All -// clients must share the secret in order to be able to sync, as it is needed -// to decrypt - -use std::fs::File; -use std::io::prelude::*; -use std::path::PathBuf; - -use eyre::{eyre, Result}; -use sodiumoxide::crypto::secretbox; - -use crate::local::history::History; -use crate::settings::Settings; - -#[derive(Debug, Serialize, Deserialize)] -pub struct EncryptedHistory { - pub ciphertext: Vec, - pub nonce: secretbox::Nonce, -} - -// Loads the secret key, will create + save if it doesn't exist -pub fn load_key(settings: &Settings) -> Result { - let path = settings.local.key_path.as_str(); - - if PathBuf::from(path).exists() { - let bytes = std::fs::read(path)?; - let key: secretbox::Key = rmp_serde::from_read_ref(&bytes)?; - Ok(key) - } else { - let key = secretbox::gen_key(); - let buf = rmp_serde::to_vec(&key)?; - - let mut file = File::create(path)?; - file.write_all(&buf)?; - - Ok(key) - } -} - -pub fn encrypt(history: &History, key: &secretbox::Key) -> Result { - // serialize with msgpack - let buf = rmp_serde::to_vec(history)?; - - let nonce = secretbox::gen_nonce(); - - let ciphertext = secretbox::seal(&buf, &nonce, key); - - Ok(EncryptedHistory { ciphertext, nonce }) -} - -pub fn decrypt(encrypted_history: &EncryptedHistory, key: &secretbox::Key) -> Result { - let plaintext = secretbox::open(&encrypted_history.ciphertext, &encrypted_history.nonce, key) - .map_err(|_| eyre!("failed to open secretbox - invalid key?"))?; - - let history = rmp_serde::from_read_ref(&plaintext)?; - - Ok(history) -} - -#[cfg(test)] -mod test { - use sodiumoxide::crypto::secretbox; - - use crate::local::history::History; - - use super::{decrypt, encrypt}; - - #[test] - fn test_encrypt_decrypt() { - let key1 = secretbox::gen_key(); - let key2 = secretbox::gen_key(); - - let history = History::new( - chrono::Utc::now(), - "ls".to_string(), - "/home/ellie".to_string(), - 0, - 1, - Some("beep boop".to_string()), - Some("booop".to_string()), - ); - - let e1 = encrypt(&history, &key1).unwrap(); - let e2 = encrypt(&history, &key2).unwrap(); - - assert_ne!(e1.ciphertext, e2.ciphertext); - assert_ne!(e1.nonce, e2.nonce); - - // test decryption works - // this should pass - match decrypt(&e1, &key1) { - Err(e) => assert!(false, "failed to decrypt, got {}", e), - Ok(h) => assert_eq!(h, history), - }; - - // this should err - match decrypt(&e2, &key1) { - Ok(_) => assert!(false, "expected an error decrypting with invalid key"), - Err(_) => {} - }; - } -} -- cgit v1.3.1