use derive_setters::Setters;
use crate::{
backend::{FileType, WriteBackend, decrypt::DecryptWriteBackend},
crypto::{aespoly1305::Key, hasher::hash},
error::{ErrorKind, RusticError, RusticResult},
repofile::{KeyFile, KeyId},
repository::{Open, Repository},
};
#[cfg_attr(feature = "clap", derive(clap::Parser))]
#[derive(Debug, Clone, Default, Setters)]
#[setters(into)]
#[non_exhaustive]
pub struct KeyOptions {
#[cfg_attr(feature = "clap", clap(long))]
pub hostname: Option<String>,
#[cfg_attr(feature = "clap", clap(long))]
pub username: Option<String>,
#[cfg_attr(feature = "clap", clap(long))]
pub with_created: bool,
}
pub(crate) fn add_current_key_to_repo<S: Open>(
repo: &Repository<S>,
opts: &KeyOptions,
pass: &str,
) -> RusticResult<KeyId> {
let key = repo.dbe().key();
add_key_to_repo(repo, opts, pass, *key)
}
pub(crate) fn init_key<S>(
repo: &Repository<S>,
opts: &KeyOptions,
pass: &str,
) -> RusticResult<(Key, KeyId)> {
let key = Key::new();
Ok((key, add_key_to_repo(repo, opts, pass, key)?))
}
pub(crate) fn add_key_to_repo<S>(
repo: &Repository<S>,
opts: &KeyOptions,
pass: &str,
key: Key,
) -> RusticResult<KeyId> {
let ko = opts.clone();
let keyfile = KeyFile::generate(key, &pass, ko.hostname, ko.username, ko.with_created)?;
let data = serde_json::to_vec(&keyfile).map_err(|err| {
RusticError::with_source(
ErrorKind::InputOutput,
"Failed to serialize keyfile to JSON.",
err,
)
})?;
let id = KeyId::from(hash(&data));
repo.be
.write_bytes(FileType::Key, &id, false, data.into())?;
Ok(id)
}