Skip to content

Commit

Permalink
feat: added encryption to profiles
Browse files Browse the repository at this point in the history
  • Loading branch information
Joel-Dandin committed Dec 30, 2024
1 parent 95ee806 commit 9237844
Showing 6 changed files with 393 additions and 15 deletions.
111 changes: 111 additions & 0 deletions src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
@@ -26,3 +26,6 @@ dirs = "5.0"
chrono = "0.4"
once_cell = "1.8"
opener = "0.5"
aes-gcm = "0.10.3"
base64 = "0.21.7"
rand = "0.8.5"
101 changes: 101 additions & 0 deletions src-tauri/src/encryption.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
use aes_gcm::{
aead::{Aead, KeyInit},
Aes256Gcm, Key, Nonce,
};
use base64::{engine::general_purpose::STANDARD as BASE64, Engine};
use rand::Rng;
use serde::{Deserialize, Serialize};
use std::fs;
use once_cell::sync::Lazy;
use std::sync::Mutex;

static ENCRYPTION_KEY: Lazy<Mutex<Vec<u8>>> = Lazy::new(|| {
Mutex::new(vec![0; 32]) // Initialize with zeros
});

pub fn set_encryption_key(key: &str) -> Result<(), String> {
let mut key_bytes = [0u8; 32];
let input_bytes = key.as_bytes();

// Pad or truncate the input key to exactly 32 bytes
let len = std::cmp::min(input_bytes.len(), 32);
key_bytes[..len].copy_from_slice(&input_bytes[..len]);

let mut current_key = ENCRYPTION_KEY.lock().map_err(|e| e.to_string())?;
*current_key = key_bytes.to_vec();
Ok(())
}

pub fn get_encryption_key() -> Result<String, String> {
let key = ENCRYPTION_KEY.lock().map_err(|e| e.to_string())?;
String::from_utf8(key.clone()).map_err(|e| e.to_string())
}

#[derive(Serialize, Deserialize)]
pub struct EncryptedData {
pub nonce: String,
pub ciphertext: String,
}

pub fn encrypt_string(data: &str) -> Result<String, String> {
let key_data = ENCRYPTION_KEY.lock().map_err(|e| e.to_string())?;
let key = Key::<Aes256Gcm>::from_slice(&key_data);
let cipher = Aes256Gcm::new(key);

let mut rng = rand::thread_rng();
let mut nonce_bytes = [0u8; 12];
rng.fill(&mut nonce_bytes);
let nonce = Nonce::from_slice(&nonce_bytes);

let ciphertext = cipher
.encrypt(nonce, data.as_bytes())
.map_err(|e| format!("Encryption failed: {}", e))?;

let encrypted_data = EncryptedData {
nonce: BASE64.encode(nonce),
ciphertext: BASE64.encode(ciphertext),
};

serde_json::to_string(&encrypted_data)
.map_err(|e| format!("Failed to serialize encrypted data: {}", e))
}

pub fn decrypt_string(encrypted_json: &str) -> Result<String, String> {
// Parse encrypted data
let encrypted_data: EncryptedData = serde_json::from_str(encrypted_json)
.map_err(|e| format!("Failed to parse encrypted data: {}", e))?;

// Decode base64
let nonce_bytes = BASE64
.decode(encrypted_data.nonce)
.map_err(|e| format!("Failed to decode nonce: {}", e))?;
let ciphertext = BASE64
.decode(encrypted_data.ciphertext)
.map_err(|e| format!("Failed to decode ciphertext: {}", e))?;

// Get the current encryption key
let key_data = ENCRYPTION_KEY.lock().map_err(|e| e.to_string())?;
let key = Key::<Aes256Gcm>::from_slice(&key_data);
let cipher = Aes256Gcm::new(key);
let nonce = Nonce::from_slice(&nonce_bytes);

// Decrypt
let plaintext = cipher
.decrypt(nonce, ciphertext.as_ref())
.map_err(|e| format!("Decryption failed: {}", e))?;

String::from_utf8(plaintext)
.map_err(|e| format!("Failed to convert decrypted data to string: {}", e))
}

pub fn write_encrypted_file(path: &std::path::Path, content: &str) -> Result<(), String> {
let encrypted = encrypt_string(content)?;
fs::write(path, encrypted)
.map_err(|e| format!("Failed to write encrypted file: {}", e))
}

pub fn read_encrypted_file(path: &std::path::Path) -> Result<String, String> {
let encrypted = fs::read_to_string(path)
.map_err(|e| format!("Failed to read encrypted file: {}", e))?;
decrypt_string(&encrypted)
}
Loading

0 comments on commit 9237844

Please sign in to comment.