Parch-backup/src/utils/security/mod.rs
2024-06-24 14:07:55 +03:30

63 lines
2.1 KiB
Rust

use aes_gcm::aead::generic_array::GenericArray;
use aes_gcm::aead::{Aead, KeyInit, Payload};
use aes_gcm::Aes256Gcm;
use hkdf::Hkdf;
use sha2::Sha256;
use std::fs;
use std::io;
use std::path::Path;
#[derive(Debug)]
pub enum CryptoError {
FileRead(io::Error),
Encryption,
Decryption,
FileWrite(io::Error),
}
impl From<io::Error> for CryptoError {
fn from(err: io::Error) -> CryptoError {
CryptoError::FileWrite(err)
}
}
/// Derives a 32-byte key from the given key using HKDF.
fn derive_key(key: &[u8]) -> [u8; 32] {
let hk = Hkdf::<Sha256>::new(None, key);
let mut okm = [0u8; 32];
hk.expand(&[], &mut okm)
.expect("32 bytes is a valid length for HKDF output");
okm
}
/// Encrypts a file using AES-GCM.
pub fn encrypt_file<P: AsRef<Path>>(file_path: P, key: &[u8]) -> Result<(), CryptoError> {
let data = fs::read(file_path.as_ref()).map_err(CryptoError::FileRead)?;
let derived_key = derive_key(key);
let cipher = Aes256Gcm::new(GenericArray::from_slice(&derived_key));
let nonce = GenericArray::from_slice(b"unique nonce"); // 12-bytes; unique per message
let ciphertext = cipher
.encrypt(nonce, Payload { msg: &data, aad: b"" })
.map_err(|_| CryptoError::Encryption)?;
fs::write(file_path.as_ref(), &ciphertext).map_err(CryptoError::FileWrite)?;
Ok(())
}
/// Decrypts a file using AES-GCM.
pub fn decrypt_file<P: AsRef<Path>>(file_path: P, key: &[u8]) -> Result<(), CryptoError> {
let cipher_text = fs::read(file_path.as_ref()).map_err(CryptoError::FileRead)?;
println!("cipher_text: {:?}", cipher_text);
let derived_key = derive_key(key);
println!("{:?}",derived_key);
let cipher = Aes256Gcm::new(GenericArray::from_slice(&derived_key));
let nonce = GenericArray::from_slice(b"unique nonce"); // Must be the same nonce used for encryption
println!("{:?}", nonce);
let plaintext = cipher
.decrypt(nonce, Payload { msg: &cipher_text, aad: b"" })
.map_err(|_| CryptoError::Decryption)?;
fs::write(file_path.as_ref(), &plaintext).map_err(CryptoError::FileWrite)?;
Ok(())
}