use crate::{
commonio,
crypter::{Decrypter, Encrypter},
key::{PublicKey, SecretKey},
};
use std::io::{self, BufRead, Read};
#[cfg(feature = "io-async")]
pub use crate::async_::bufread::*;
#[derive(Debug)]
pub struct SaltlickDecrypter<R> {
decrypter: Decrypter,
inner: R,
}
impl<R> SaltlickDecrypter<R> {
pub fn new(public_key: PublicKey, secret_key: SecretKey, reader: R) -> SaltlickDecrypter<R> {
SaltlickDecrypter {
decrypter: Decrypter::new(public_key, secret_key),
inner: reader,
}
}
pub fn new_deferred<F>(reader: R, lookup_fn: F) -> SaltlickDecrypter<R>
where
F: FnOnce(&PublicKey) -> Option<SecretKey> + 'static,
{
SaltlickDecrypter {
decrypter: Decrypter::new_deferred(lookup_fn),
inner: reader,
}
}
pub fn into_inner(self) -> R {
self.inner
}
}
impl<R: BufRead> Read for SaltlickDecrypter<R> {
fn read(&mut self, output: &mut [u8]) -> io::Result<usize> {
commonio::read(&mut self.inner, &mut self.decrypter, output)
}
}
#[derive(Debug)]
pub struct SaltlickEncrypter<R> {
encrypter: Encrypter,
inner: R,
}
impl<R> SaltlickEncrypter<R> {
pub fn new(public_key: PublicKey, reader: R) -> SaltlickEncrypter<R> {
SaltlickEncrypter {
encrypter: Encrypter::new(public_key),
inner: reader,
}
}
pub fn set_block_size(&mut self, block_size: usize) {
self.encrypter.set_block_size(block_size);
}
pub fn into_inner(self) -> R {
self.inner
}
}
impl<R: BufRead> Read for SaltlickEncrypter<R> {
fn read(&mut self, output: &mut [u8]) -> io::Result<usize> {
commonio::read(&mut self.inner, &mut self.encrypter, output)
}
}
#[cfg(test)]
mod tests {
use super::{SaltlickDecrypter, SaltlickEncrypter};
use crate::{key::gen_keypair, testutils::random_bytes};
use std::io::{BufReader, Cursor, Read};
#[test]
fn round_trip_test() {
for size in &[
1,
10 * 1024,
32 * 1024,
100 * 1024,
200 * 1024,
10 * 1024 * 1024,
] {
let random_data = random_bytes(0, *size);
let reader = Cursor::new(random_data.clone());
let (public_key, secret_key) = gen_keypair();
let mut encrypter = SaltlickEncrypter::new(public_key, reader);
encrypter.set_block_size(1024);
let mut decrypter =
SaltlickDecrypter::new_deferred(BufReader::new(encrypter), |_| Some(secret_key));
let mut output = Vec::new();
decrypter.read_to_end(&mut output).unwrap();
assert_eq!(&random_data[..], &output[..]);
let encrypter = decrypter.into_inner();
let _ = encrypter.into_inner();
}
}
#[test]
fn corrupt_value_test() {
let random_data = random_bytes(0, 100 * 1024);
let (public_key, secret_key) = gen_keypair();
let mut encrypter = SaltlickEncrypter::new(public_key.clone(), Cursor::new(random_data));
let mut ciphertext = Vec::new();
encrypter.read_to_end(&mut ciphertext).unwrap();
let index = ciphertext.len() - 5;
ciphertext[index] = ciphertext[index].wrapping_add(1);
let mut decrypter = SaltlickDecrypter::new(public_key, secret_key, Cursor::new(ciphertext));
let mut output = Vec::new();
assert!(decrypter.read_to_end(&mut output).is_err());
}
#[test]
fn incomplete_stream_test() {
let random_data = random_bytes(0, 100 * 1024);
let (public_key, secret_key) = gen_keypair();
let mut encrypter = SaltlickEncrypter::new(public_key.clone(), Cursor::new(random_data));
let mut ciphertext = Vec::new();
encrypter.read_to_end(&mut ciphertext).unwrap();
ciphertext.resize(ciphertext.len() - 5, 0);
let mut decrypter = SaltlickDecrypter::new(public_key, secret_key, Cursor::new(ciphertext));
let mut output = Vec::new();
assert!(decrypter.read_to_end(&mut output).is_err());
}
}