Added enc::ser_singleton() with options

Fortune for transfer's current commit: Future small blessing − 末小吉
basic
Avril 3 years ago
parent 035dabf869
commit 40656d6cc3
Signed by: flanchan
GPG Key ID: 284488987C31F630

26
Cargo.lock generated

@ -460,6 +460,12 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "itoa"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
[[package]]
name = "lazy_static"
version = "1.4.0"
@ -788,6 +794,12 @@ version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
[[package]]
name = "ryu"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
[[package]]
name = "scopeguard"
version = "1.1.0"
@ -824,6 +836,17 @@ dependencies = [
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f690853975602e1bfe1ccbf50504d67174e3bcf340f23b5ea9992e0587a52d8"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "sha2"
version = "0.9.8"
@ -932,8 +955,10 @@ version = "0.1.0"
dependencies = [
"async-compression",
"base64 0.13.0",
"bytes 1.1.0",
"color-eyre",
"cryptohelpers",
"futures",
"getrandom 0.2.3",
"lazy_static",
"log",
@ -941,6 +966,7 @@ dependencies = [
"pretty_env_logger",
"serde",
"serde_cbor",
"serde_json",
"tokio 1.12.0",
]

@ -8,8 +8,10 @@ edition = "2021"
[dependencies]
async-compression = { version = "0.3.8", features = ["tokio", "brotli"] }
base64 = "0.13.0"
bytes = "1.1.0"
color-eyre = { version = "0.5.11", default-features = false }
cryptohelpers = { version = "1.8.2", features = ["full"] }
futures = "0.3.17"
getrandom = "0.2.3"
lazy_static = "1.4.0"
log = "0.4.14"
@ -17,4 +19,5 @@ openssl = "0.10.36"
pretty_env_logger = "0.4.0"
serde = { version = "1.0.130", features = ["derive"] }
serde_cbor = "0.11.2"
serde_json = "1.0.68"
tokio = { version = "1.12.0", features = ["full"] }

@ -0,0 +1,217 @@
//! Encodings
use super::*;
use std::{fmt, error};
use bytes::{
Buf,
Bytes,
};
use std::io;
use tokio::io::{
AsyncRead, AsyncWrite,
AsyncReadExt, AsyncWriteExt,
};
use serde::{
Serialize,
Deserialize
};
#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy, PartialOrd, Ord)]
pub enum CompressionKind
{
Brotli,
Xz,
GZip,
}
impl Default for CompressionKind
{
#[inline]
fn default() -> Self
{
Self::Brotli
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)]
pub enum EncryptionKind
{
Chacha20((key::Key, key::IV))
}
impl Default for EncryptionKind
{
#[inline]
fn default() -> Self
{
Self::Chacha20(cha::keygen())
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)]
pub enum SerialFormat
{
/// CBOR
Binary,
/// JSON
Text,
}
impl Default for SerialFormat
{
#[inline]
fn default() -> Self
{
Self::Binary
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)]
pub struct SendOpt
{
pub comp: Option<CompressionKind>,
pub encrypt: Option<EncryptionKind>,
pub format: SerialFormat,
}
pub const DEFAULT_BUFSIZE: usize = 4096;
pub async fn cha_copy<F, T, const BUFSIZE: usize, const DECRYPT: bool>(from: &mut F, to: &mut T, key: &key::Key, iv: &key::IV) -> io::Result<(usize, usize)>
where F: AsyncRead + Unpin + ?Sized,
T: AsyncWrite + Unpin + ?Sized
{
let mut written=0;
let mut read=0;
let mut r;
let mut buffer = [0u8; BUFSIZE];
let mut cbuffer = [0u8; BUFSIZE];
let mut crypter = if DECRYPT {
cha::decrypter(key, iv)
} else {
cha::encrypter(key, iv)
}?;
while { r = from.read(&mut buffer[..]).await?; r > 0 } {
read += r;
r = crypter.update(&buffer[..r], &mut cbuffer[..])?;
to.write(&cbuffer[..r]).await?;
written += r;
}
Ok((written, read))
}
async fn ser_singleton_inner<T: Serialize>(value: &T, how: &SendOpt) -> Result<Vec<u8>, SendErrorKind>
{
let ser = match how.format {
SerialFormat::Text => serde_json::to_vec(value)?,
SerialFormat::Binary => serde_cbor::to_vec(value)?,
};
let mut a;
let mut b;
let reader: &mut (dyn AsyncRead + Unpin) =
if let Some(comp) = &how.comp {
match comp {
CompressionKind::Brotli => {
a = async_compression::tokio::bufread::BrotliEncoder::new(tokio::io::BufReader::new(&ser[..]));
&mut a
},
_ => unimplemented!("Xz and GZip currently unimplemented."),
}
} else {
b = &ser[..];
&mut b
};
let mut ser = Vec::with_capacity(ser.len());
if let Some(enc) = &how.encrypt {
match enc {
EncryptionKind::Chacha20((k, iv)) => {
self::cha_copy::<_, _, 4096, false>(reader, &mut ser, k, iv).await?;
},
}
} else {
tokio::io::copy(reader, &mut ser).await?;
}
Ok(ser)
// inner(value, how).map(|res| res.map_err(|k| SendError(Box::new((k, how.clone())))))
}
#[inline(always)] pub fn ser_singleton<'a, T: Serialize>(value: &'a T, how: &'a SendOpt) -> impl Future<Output = Result<Vec<u8>, SendError>> + 'a
{
use futures::prelude::*;
// hack to avoid having to enable `try{}` feature :/
ser_singleton_inner(value, how).map_err(|k| SendError(Box::new((k, how.clone()))))
}
pub async fn write_singleton<T: Serialize, S: ?Sized + AsyncWrite + Unpin>(to: &mut S, value: &T, how: &SendOpt) -> Result<usize, SendError>
{
Ok(0)
}
#[derive(Debug)]
pub enum SendErrorKind
{
/// Invalid serialised format
Format,
/// Compression
Compress,
/// Encryption
Encrypt,
/// Misc. IO
//TODO: Disambiguate when this happens into the two above cases.
IO(io::Error),
}
#[derive(Debug)]
pub struct SendError(Box<(SendErrorKind, SendOpt)>);
impl error::Error for SendError
{
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
Some(match &self.0.0
{
SendErrorKind::IO(io) => io,
_ => return None,
})
}
}
impl fmt::Display for SendError
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
write!(f, "error when serialising object with params {:?}: ", self.0.1)?;
match self.0.0 {
SendErrorKind::Format => write!(f, "failed to serialise object to data"),
SendErrorKind::Compress => write!(f, "failed to compress data"),
SendErrorKind::Encrypt => write!(f, "failed to encrypt data"),
SendErrorKind::IO(_) => write!(f, "i/o failure"),
}
}
}
impl From<io::Error> for SendErrorKind
{
fn from(from: io::Error) -> Self
{
Self::IO(from)
}
}
impl From<serde_cbor::Error> for SendErrorKind
{
#[inline] fn from(_: serde_cbor::Error) -> Self
{
Self::Format
}
}
impl From<serde_json::Error> for SendErrorKind
{
#[inline] fn from(_: serde_json::Error) -> Self
{
Self::Format
}
}

@ -8,6 +8,25 @@ use std::{
slice,
fmt,
};
pub use std::{
marker::{
Send, Sync, Unpin,
},
convert::{
Infallible,
TryFrom,
TryInto
},
};
pub use tokio::{
io::{
AsyncWriteExt,
AsyncReadExt,
},
task::JoinHandle,
};
#[derive(Debug, Clone)]
pub struct HexStringIter<I>(I, [u8; 2]);

@ -13,10 +13,12 @@ use color_eyre::{
},
SectionExt, Help,
};
use futures::Future;
mod ext;
mod key;
mod cha;
mod enc;
mod config;
mod args;

@ -13,8 +13,10 @@ pub struct Request
}
pub async fn read_req<T>(mut from: T, key: ) -> eyre::Result<Request>
where T: AsyncRead + Unpin
{
todo!("how do we handle encryption of the request data? eh... boring")
}

Loading…
Cancel
Save