use url::Url;
use super::hkdf::{derive_auth_key, derive_file_key, derive_meta_key};
use super::{b64, rand_bytes};
use crate::api::url::UrlBuilder;
use crate::file::remote_file::RemoteFile;
const KEY_NONCE_LEN: usize = 12;
pub struct KeySet {
secret: Vec<u8>,
nonce: [u8; KEY_NONCE_LEN],
file_key: Option<Vec<u8>>,
auth_key: Option<Vec<u8>>,
meta_key: Option<Vec<u8>>,
}
impl KeySet {
pub fn new(secret: Vec<u8>, nonce: [u8; 12]) -> Self {
Self {
secret,
nonce,
file_key: None,
auth_key: None,
meta_key: None,
}
}
pub fn from(file: &RemoteFile, password: Option<&String>) -> Self {
let mut set = Self::new(file.secret_raw().clone(), [0; 12]);
set.derive();
if let Some(password) = password {
set.derive_auth_password(password, &UrlBuilder::download(&file, true));
}
set
}
pub fn generate(derive: bool) -> Self {
let mut secret = vec![0u8; 16];
let mut iv = [0u8; 12];
rand_bytes(&mut secret).expect("failed to generate crypto secure random secret");
rand_bytes(&mut iv).expect("failed to generate crypto secure random input vector");
let mut key = Self::new(secret, iv);
if derive {
key.derive();
}
key
}
pub fn derive(&mut self) {
self.file_key = Some(derive_file_key(&self.secret));
self.auth_key = Some(derive_auth_key(&self.secret, None, None));
self.meta_key = Some(derive_meta_key(&self.secret));
}
pub fn derive_auth_password(&mut self, pass: &str, url: &Url) {
self.auth_key = Some(derive_auth_key(&self.secret, Some(pass), Some(url)));
}
pub fn secret(&self) -> &[u8] {
&self.secret
}
pub fn secret_encoded(&self) -> String {
b64::encode(self.secret())
}
pub fn nonce(&self) -> &[u8] {
&self.nonce
}
pub fn set_nonce(&mut self, nonce: [u8; KEY_NONCE_LEN]) {
self.nonce = nonce;
}
pub fn file_key(&self) -> Option<&Vec<u8>> {
self.file_key.as_ref()
}
pub fn auth_key(&self) -> Option<&Vec<u8>> {
self.auth_key.as_ref()
}
pub fn auth_key_encoded(&self) -> Option<String> {
self.auth_key().map(|key| b64::encode(key))
}
pub fn meta_key(&self) -> Option<&Vec<u8>> {
self.meta_key.as_ref()
}
}