use crate::{cipher, utils::get_pad_key_and_nonce, utils::xor, EncryptedChunk, Error, Result};
use bytes::Bytes;
use rayon::prelude::*;
use std::io::Cursor;
use xor_name::XorName;
pub fn decrypt_sorted_set(
src_hashes: Vec<XorName>,
encrypted_chunks: &[&EncryptedChunk],
child_level: usize,
) -> Result<Bytes> {
let decrypted_chunks: Vec<Bytes> = encrypted_chunks
.par_iter()
.enumerate()
.map(|(chunk_index, chunk)| {
decrypt_chunk(chunk_index, &chunk.content, &src_hashes, child_level)
})
.collect::<Result<Vec<_>>>()?;
let total_len = decrypted_chunks.iter().map(|c| c.len()).sum();
let mut all_bytes = Vec::with_capacity(total_len);
for chunk in &decrypted_chunks {
all_bytes.extend_from_slice(chunk);
}
Ok(Bytes::from(all_bytes))
}
pub fn decrypt_chunk(
chunk_index: usize,
content: &Bytes,
src_hashes: &[XorName],
child_level: usize,
) -> Result<Bytes> {
let pki = get_pad_key_and_nonce(chunk_index, src_hashes, child_level)?;
let (pad, key, nonce) = pki;
let xored = xor(content, &pad);
let decrypted = cipher::decrypt(xored, &key, &nonce)?;
let mut decompressed = Vec::new();
let mut cursor = Cursor::new(&decrypted);
brotli::BrotliDecompress(&mut cursor, &mut decompressed).map_err(|_| Error::Compression)?;
Ok(Bytes::from(decompressed))
}