use zeroize::Zeroize;
#[derive(Clone, Copy, Debug, PartialEq)]
pub(crate) enum EncryptionVersion {
V3ChaCha = 3,
V2Scrypt = 2,
V1Xor = 1,
}
pub(crate) enum EncryptionAuxData {
V3ChaCha(
(
u8,
crate::encrypt_chacha::EncryptionSalt,
crate::encrypt_chacha::EncryptionNonce,
),
),
V2Scrypt((u8, crate::encrypt_scrypt::EncryptionSalt)),
V1Xor(crate::encrypt_xor::EncryptionSalt),
}
pub(crate) trait Encryptor {
fn encrypt(
unencrypted_data: &mut Vec<u8>,
password: &str,
aux_data: &EncryptionAuxData,
) -> Result<(), String>;
fn decrypt(
encrypted_data: &mut Vec<u8>,
password: &str,
aux_data: &EncryptionAuxData,
) -> Result<(), String>;
fn generate_aux_data() -> EncryptionAuxData;
}
impl EncryptionVersion {
pub(crate) fn from_u8(byte: u8) -> Result<Self, String> {
match byte {
3 => Ok(Self::V3ChaCha),
2 => Ok(Self::V2Scrypt),
1 => Ok(Self::V1Xor),
_ => Err(format!("Invalid encryption version {}", byte)),
}
}
}
impl Zeroize for EncryptionAuxData {
fn zeroize(&mut self) {
match self {
Self::V3ChaCha((_rounds, ref mut salt, ref mut nonce)) => {
salt.zeroize();
nonce.zeroize();
}
Self::V2Scrypt((_rounds, ref mut salt)) => {
salt.zeroize();
}
Self::V1Xor(ref mut salt) => {
salt.zeroize();
}
}
}
}
impl EncryptionAuxData {
pub(crate) fn version(&self) -> Result<EncryptionVersion, String> {
match &self {
Self::V3ChaCha(_) => Ok(EncryptionVersion::V3ChaCha),
Self::V2Scrypt(_) => Ok(EncryptionVersion::V2Scrypt),
Self::V1Xor(_) => Ok(EncryptionVersion::V1Xor),
}
}
pub(crate) fn check_version(
&self,
encryption_version: EncryptionVersion,
) -> Result<(), String> {
let expected_version = self.version()?;
if encryption_version != expected_version {
return Err(format!(
"Invalid encryption version, {:?} vs {:?}",
encryption_version, expected_version
));
}
Ok(())
}
}