This commit is contained in:
2026-05-10 18:55:21 -05:00
parent 33f567d2bc
commit e4a3eaae08
8 changed files with 122 additions and 71 deletions
+46 -11
View File
@@ -1,7 +1,9 @@
use std::ffi::OsString;
use std::io::Write;
use std::path::{Path, PathBuf};
use age::ssh::Identity;
use flate2::Compression;
use flate2::read::GzDecoder;
use flate2::write::GzEncoder;
use clap::{Parser, Subcommand};
use crate::error::DrawerError;
@@ -105,7 +107,40 @@ impl DrawerOperation {
}
fn perform_open(&self) -> Result<(), DrawerError> {
todo!()
let encrypted = std::fs::read(&self.drawer_file)
.map_err(|_| DrawerError::DrawerFileNotFound(self.drawer_file.clone()))?;
let decrypted = self.decrypt(encrypted)?;
let cursor = std::io::Cursor::new(decrypted);
let gz = GzDecoder::new(cursor);
let mut archive = tar::Archive::new(gz);
archive.unpack(&self.target_path)
.map_err(|_| DrawerError::UntarFailed)?;
Ok(())
}
fn decrypt(&self, encrypted: Vec<u8>) -> Result<Vec<u8>, DrawerError> {
let (key_path, identity) = self.identity()?;
let decryptor = age::Decryptor::new(encrypted.as_slice())
.map_err(|_| DrawerError::DecryptFailed(self.drawer_file.clone(), key_path.clone()))?;
let mut decrypted: Vec<u8> = Vec::new();
let mut stream = decryptor.decrypt(std::iter::once(&identity as &dyn age::Identity))
.map_err(|_| DrawerError::DecryptFailed(self.drawer_file.clone(), key_path.clone()))?;
std::io::Read::read_to_end(&mut stream, &mut decrypted)
.map_err(|_| DrawerError::DecryptFailed(self.drawer_file.clone(), key_path.clone()))?;
Ok(decrypted)
}
fn identity(&self) -> Result<(PathBuf, Identity), DrawerError> {
let key_path = self.key_path()?;
let file = std::fs::File::open(&key_path)
.map_err(|_| DrawerError::KeyInvalid(key_path.clone()))?;
let reader = std::io::BufReader::new(file);
let identity = age::ssh::Identity::from_buffer(reader, None)
.map_err(|_| DrawerError::DecryptFailed(self.drawer_file.clone(), key_path.clone()))?;
Ok((key_path, identity))
}
fn perform_close(&self) -> Result<(), DrawerError> {
@@ -121,12 +156,14 @@ impl DrawerOperation {
.map_err(|_| DrawerError::TarFailed)?;
}
let key_path = self.key_path()?;
let file = std::fs::File::open(&key_path)
.map_err(|_| DrawerError::KeyInvalid(key_path.clone()))?;
let reader = std::io::BufReader::new(file);
let identity = age::ssh::Identity::from_buffer(reader, None)
.map_err(|_| DrawerError::EncryptFailed)?;
let encrypted = self.encrypt(&buf)?;
std::fs::write(&self.drawer_file, &encrypted)
.map_err(|_| DrawerError::WriteFailed(self.drawer_file.clone()))
}
fn encrypt(&self, buf: &[u8]) -> Result<Vec<u8>, DrawerError> {
let (_, identity) = self.identity()?;
let recipient = age::ssh::Recipient::try_from(identity)
.map_err(|_| DrawerError::EncryptFailed)?;
@@ -136,11 +173,9 @@ impl DrawerOperation {
).map_err(|_| DrawerError::EncryptFailed)?;
let mut writer = encryptor.wrap_output(&mut encrypted)
.map_err(|_| DrawerError::EncryptFailed)?;
writer.write_all(&buf).map_err(|_| DrawerError::EncryptFailed)?;
writer.write_all(buf).map_err(|_| DrawerError::EncryptFailed)?;
writer.finish().map_err(|_| DrawerError::EncryptFailed)?;
std::fs::write(&self.drawer_file, &encrypted)
.map_err(|_| DrawerError::WriteFailed(self.drawer_file.clone()))
Ok(encrypted)
}
pub fn validate(&self) -> Result<(), DrawerError> {