use std::io::{Cursor, Read};
use crate::{
Result,
EncryptionAlgorithm,
HeaderCoding,
ValueEncoder,
ValueDecoder,
header::version1::{PBEHeader, KDFParameters},
ZffError,
ZffErrorKind,
KDFScheme,
PBEScheme,
Encryption,
};
use crate::version1::{
HEADER_IDENTIFIER_ENCRYPTION_HEADER,
ERROR_HEADER_DECODER_UNKNOWN_ENCRYPTION_ALGORITHM,
};
#[derive(Debug,Clone,Eq,PartialEq)]
pub struct EncryptionHeader {
version: u8,
pbe_header: PBEHeader,
algorithm: EncryptionAlgorithm,
encrypted_encryption_key: Vec<u8>,
encrypted_header_nonce: [u8; 12],
}
impl EncryptionHeader {
pub fn new(
version: u8,
pbe_header: PBEHeader,
algorithm: EncryptionAlgorithm,
encrypted_encryption_key: Vec<u8>, encrypted_header_nonce: [u8; 12], ) -> EncryptionHeader {
Self {
version,
pbe_header,
algorithm,
encrypted_encryption_key,
encrypted_header_nonce
}
}
pub fn algorithm(&self) -> &EncryptionAlgorithm {
&self.algorithm
}
pub fn pbe_header(&self) -> &PBEHeader {
&self.pbe_header
}
pub fn nonce(&self) -> &[u8; 12] {
&self.encrypted_header_nonce
}
pub fn decrypt_encryption_key<P: AsRef<[u8]>>(&self, password: P) -> Result<Vec<u8>> {
match self.pbe_header.kdf_scheme() {
KDFScheme::PBKDF2SHA256 => match self.pbe_header.kdf_parameters() {
KDFParameters::PBKDF2SHA256Parameters(parameters) => {
let iterations = parameters.iterations();
let salt = parameters.salt();
match self.pbe_header.encryption_scheme() {
PBEScheme::AES128CBC => Encryption::decrypt_pbkdf2sha256_aes128cbc(
iterations.into(),
salt,
self.pbe_header.nonce(),
&password,
&self.encrypted_encryption_key
),
PBEScheme::AES256CBC => Encryption::decrypt_pbkdf2sha256_aes256cbc(
iterations.into(),
salt,
self.pbe_header.nonce(),
&password,
&self.encrypted_encryption_key
),
}
}
},
_ => Err(ZffError::new(ZffErrorKind::MalformedHeader, ""))
}
}
}
impl HeaderCoding for EncryptionHeader {
type Item = EncryptionHeader;
fn identifier() -> u32 {
HEADER_IDENTIFIER_ENCRYPTION_HEADER
}
fn version(&self) -> u8 {
self.version
}
fn encode_header(&self) -> Vec<u8> {
let mut vec = vec![self.version];
vec.append(&mut self.pbe_header.encode_directly());
vec.push(self.algorithm.clone() as u8);
vec.append(&mut self.encrypted_encryption_key.encode_directly());
vec.append(&mut self.encrypted_header_nonce.encode_directly());
vec
}
fn decode_content(data: Vec<u8>) -> Result<EncryptionHeader> {
let mut cursor = Cursor::new(data);
let header_version = u8::decode_directly(&mut cursor)?;
let pbe_header = PBEHeader::decode_directly(&mut cursor)?;
let encryption_algorithm = match u8::decode_directly(&mut cursor)? {
0 => EncryptionAlgorithm::AES128GCMSIV,
1 => EncryptionAlgorithm::AES256GCMSIV,
_ => return Err(ZffError::new_header_decode_error(ERROR_HEADER_DECODER_UNKNOWN_ENCRYPTION_ALGORITHM)),
};
let key_length = u64::decode_directly(&mut cursor)? as usize;
let mut encryption_key = vec![0u8; key_length];
cursor.read_exact(&mut encryption_key)?;
let mut nonce = [0; 12];
cursor.read_exact(&mut nonce)?;
Ok(EncryptionHeader::new(header_version, pbe_header, encryption_algorithm, encryption_key, nonce))
}
}