use keyring::Entry;
use std::path::PathBuf;
const SERVICE: &str = "ENKRYPTIT";
use crate::{conversions::convert_key, errors::EnkryptitError};
fn key_path(filename: &str) -> Result<PathBuf, EnkryptitError> {
let mut path = dirs::home_dir().ok_or(EnkryptitError::HomeNotFound)?;
path.push("private_keys");
std::fs::create_dir_all(&path)?;
let file_path = PathBuf::from(filename);
let stem = if file_path.extension().and_then(|e| e.to_str()) == Some("encky") {
file_path.file_stem()
} else {
file_path.file_name()
}
.ok_or(EnkryptitError::FileError)?
.to_string_lossy()
.into_owned();
path.push(format!("enkryptit_{}", stem));
Ok(path)
}
pub fn load_key_from_os(filename: &str) -> Result<[u8; 32], EnkryptitError> {
let user = format!("enkryptit{}", filename);
let entry = Entry::new(SERVICE, &user)?;
let hex_key = entry.get_password()?;
let bytes = hex::decode(hex_key)?;
if bytes.len() != 32 {
return Err(EnkryptitError::InvalidKeyLength);
}
let mut key = [0u8; 32];
key.copy_from_slice(&bytes);
Ok(key)
}
pub fn save_key_in_os(filename: &str, key: [u8; 32]) -> Result<(), EnkryptitError> {
let user = format!("enkryptit{}", filename);
let entry = Entry::new("ENKRYPTIT", &user)?;
entry.set_password(&hex::encode(key))?;
Ok(())
}
pub fn save_key_in_file(filename: &str, key: [u8; 32]) -> Result<(), EnkryptitError> {
let path = key_path(filename)?;
std::fs::write(path, hex::encode(key))?;
Ok(())
}
pub fn load_key_from_file(filename: &str) -> Result<[u8; 32], EnkryptitError> {
let path = key_path(filename)?;
let key = std::fs::read(path)?;
convert_key(hex::decode(key)?)
}