use crate::quasor::{Error, Quasor};
use rayon::prelude::*;
const CHUNK_SIZE: usize = 1024 * 1024;
impl Quasor {
pub fn encrypt_parallel(
&self,
plaintext: &[u8],
ad: &[u8],
) -> (Vec<u8>, Vec<Vec<u8>>, Vec<Vec<u8>>) {
let results: Vec<(Vec<u8>, Vec<u8>, Vec<u8>)> = plaintext
.par_chunks(CHUNK_SIZE)
.enumerate()
.map(|(i, chunk)| {
let mut chunk_key_hasher = blake3::Hasher::new_keyed(self.master_key());
chunk_key_hasher.update(b"chunk-key");
chunk_key_hasher.update(&(i as u64).to_le_bytes());
let chunk_key: [u8; 32] = chunk_key_hasher.finalize().into();
let chunk_quasor = Quasor::from_raw_key(chunk_key);
let (ct, tag, nonce) = chunk_quasor.encrypt(chunk, ad);
(ct, tag, nonce)
})
.collect();
let mut ciphertexts = Vec::with_capacity(results.len());
let mut tags = Vec::with_capacity(results.len());
let mut nonces = Vec::with_capacity(results.len());
for (ct, tag, nonce) in results {
ciphertexts.push(ct);
tags.push(tag);
nonces.push(nonce);
}
let ciphertext = ciphertexts.into_iter().flatten().collect();
(ciphertext, tags, nonces)
}
pub fn decrypt_parallel(
&self,
ciphertext: &[u8],
ad: &[u8],
chunk_tags: &[Vec<u8>],
chunk_nonces: &[Vec<u8>],
) -> Result<Vec<u8>, Error> {
let plaintexts: Result<Vec<Vec<u8>>, Error> = ciphertext
.par_chunks(CHUNK_SIZE)
.zip(chunk_tags.par_iter())
.zip(chunk_nonces.par_iter())
.enumerate()
.map(|(i, ((chunk, tag), nonce))| {
let mut chunk_key_hasher = blake3::Hasher::new_keyed(self.master_key());
chunk_key_hasher.update(b"chunk-key");
chunk_key_hasher.update(&(i as u64).to_le_bytes());
let chunk_key: [u8; 32] = chunk_key_hasher.finalize().into();
let chunk_quasor = Quasor::from_raw_key(chunk_key);
chunk_quasor.decrypt(nonce, chunk, ad, tag)
})
.collect();
let plaintexts = plaintexts?;
let plaintext = plaintexts.into_iter().flatten().collect();
Ok(plaintext)
}
}