chacha sink works

testing
Avril 4 years ago
parent 89f706d07d
commit dbfcaafdb0
Signed by: flanchan
GPG Key ID: 284488987C31F630

40
Cargo.lock generated

@ -47,9 +47,10 @@ version = "0.1.0"
dependencies = [ dependencies = [
"base64", "base64",
"getrandom 0.2.2", "getrandom 0.2.2",
"hex-literal 0.3.1", "hex-literal",
"khash", "khash",
"openssl", "openssl",
"smallvec",
] ]
[[package]] [[package]]
@ -114,39 +115,20 @@ dependencies = [
"wasi 0.10.2+wasi-snapshot-preview1", "wasi 0.10.2+wasi-snapshot-preview1",
] ]
[[package]]
name = "hex-literal"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "961de220ec9a91af2e1e5bd80d02109155695e516771762381ef8581317066e0"
dependencies = [
"hex-literal-impl",
"proc-macro-hack",
]
[[package]] [[package]]
name = "hex-literal" name = "hex-literal"
version = "0.3.1" version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5af1f635ef1bc545d78392b136bfe1c9809e029023c84a3638a864a10b8819c8" checksum = "5af1f635ef1bc545d78392b136bfe1c9809e029023c84a3638a864a10b8819c8"
[[package]]
name = "hex-literal-impl"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "853f769599eb31de176303197b7ba4973299c38c7a7604a6bc88c3eef05b9b46"
dependencies = [
"proc-macro-hack",
]
[[package]] [[package]]
name = "khash" name = "khash"
version = "2.0.3" version = "2.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "193f6499a7299fa3f470fac8c79bbd148370f6085b0c2fa4f32a03f517f7a6e7" checksum = "c266778a8846ff4ebcdeb6bbd7ac651d2c02a2cabb53fbc7198398dcfcd98daa"
dependencies = [ dependencies = [
"getrandom 0.1.16", "getrandom 0.1.16",
"hex-literal 0.2.1", "hex-literal",
"rustc_version", "rustc_version",
"sha2", "sha2",
] ]
@ -202,12 +184,6 @@ version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
[[package]]
name = "proc-macro-hack"
version = "0.5.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
[[package]] [[package]]
name = "rustc_version" name = "rustc_version"
version = "0.2.3" version = "0.2.3"
@ -245,6 +221,12 @@ dependencies = [
"opaque-debug", "opaque-debug",
] ]
[[package]]
name = "smallvec"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e"
[[package]] [[package]]
name = "typenum" name = "typenum"
version = "1.13.0" version = "1.13.0"

@ -7,8 +7,9 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
base64 = "0.13.0" base64 = "0.13"
getrandom = "0.2.2" getrandom = "0.2"
hex-literal = "0.3.1" hex-literal = "0.3"
khash = {version = "2.0.3", default-features=false} khash = {version = "2.0.4", default-features=false}
openssl = "0.10.32" openssl = "0.10"
smallvec = {version = "1.6.1", features=["write", "union"]}

@ -114,3 +114,9 @@ impl<I: Iterator<Item = u8> + Clone> fmt::Display for HexStringIter<I>
self.clone().consume(f) self.clone().consume(f)
} }
} }
#[macro_export] macro_rules! prog1 {
($first:expr, $($rest:expr);+ $(;)?) => {
($first, $( $rest ),+).0
}
}

@ -1,10 +1,11 @@
#[macro_use] extern crate hex_literal; #[macro_use] extern crate hex_literal;
mod ext; use ext::*; mod ext; #[macro_use] use ext::*;
mod key; mod key;
mod cha; mod cha;
mod stream;
use key::{Key, IV}; use key::{Key, IV};
@ -19,7 +20,10 @@ fn encrypt((key, iv): &(Key, IV), input: impl AsRef<[u8]>) -> Result<String, ope
let n = enc.update(&input[..], &mut output[..])?; let n = enc.update(&input[..], &mut output[..])?;
eprintln!("(enc) Written {} bytes", n); eprintln!("(enc) Written {} bytes", n);
enc.finalize(&mut output[..n])?;
println!(">> {}", (&output[..n]).hex());
assert!(enc.finalize(&mut output[..n])? == 0);
println!(">> {}", (&output[..n]).hex());
Ok(base64::encode(&output[..n])) Ok(base64::encode(&output[..n]))
} }
@ -35,7 +39,11 @@ fn decrypt((key, iv): &(Key, IV), input: impl AsRef<str>) -> Result<Vec<u8>, ope
let n = dec.update(&input[..], &mut output[..])?; let n = dec.update(&input[..], &mut output[..])?;
eprintln!("(dec) Written {} bytes", n); eprintln!("(dec) Written {} bytes", n);
dec.finalize(&mut output[..n])?;
println!(">> {}", (&output[..n]).hex());
assert!(dec.finalize(&mut output[..n])? == 0);
// assert!(dec.finalize(&mut output[..n])? == 0);
println!(">> {}", (&output[..n]).hex());
output.truncate(n); output.truncate(n);
Ok(output) Ok(output)

@ -0,0 +1,175 @@
#![allow(dead_code)]
use super::*;
use key::*;
use std::io::{self, Write};
use std::fmt;
use openssl::{
symm::Crypter,
error::ErrorStack,
};
use smallvec::SmallVec;
pub const BUFFER_SIZE: usize = 1024;
pub type Error = ErrorStack;
/// ChaCha Sink
//#[derive(Debug)]
pub struct Sink<W>
{
stream: W,
crypter: Crypter, // for chacha, finalize does nothing it seems. we can also call it multiple times.
buffer: SmallVec<[u8; BUFFER_SIZE]> // used to buffer the operation
}
impl<W: fmt::Debug> fmt::Debug for Sink<W>
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
write!(f, "Sink({:?}, ({} buffer cap))", self.stream, self.buffer.capacity())
}
}
impl<W> Sink<W>
where W: Write
{
/// Create a new Chacha Sink stream wrapper
pub fn new(stream: W, crypter: Crypter) -> Self
{
Self{stream, crypter, buffer: SmallVec::new()}
}
/// Create an encrypting Chacha Sink stream wrapper
pub fn encrypt(stream: W, key: Key, iv: IV) -> Result<Self, Error>
{
Ok(Self::new(stream, cha::encrypter(key, iv)?))
}
/// Create a decrypting Chacha Sink stream wrapper
pub fn decrypt(stream: W, key: Key, iv: IV) -> Result<Self, Error>
{
Ok(Self::new(stream, cha::decrypter(key, iv)?))
}
/// Consume into the inner stream
pub fn into_inner(self) -> W
{
self.stream
}
/// Consume into the inner stream and crypter
pub fn into_parts(self) -> (W, Crypter)
{
(self.stream, self.crypter)
}
/// The crypter of this instance
pub fn crypter(&self) -> &Crypter
{
&self.crypter
}
/// The crypter of this instance
pub fn crypter_mut(&mut self) -> &mut Crypter
{
&mut self.crypter
}
/// The inner stream
pub fn inner(&self) -> &W
{
&self.stream
}
/// The inner stream
pub fn inner_mut(&mut self) -> &mut W
{
&mut self.stream
}
}
impl<W: Write> Write for Sink<W>
{
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
prog1!{
{
self.buffer.write_all(buf).unwrap();
let n = self.crypter.update(&buf[..], &mut self.buffer[..])?;
self.crypter.finalize(&mut self.buffer[..n])?; // I don't think this is needed
self.stream.write(&self.buffer[..n])
},
self.buffer.clear();
}
}
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
prog1!{
{
self.buffer.write_all(buf).unwrap();
let n = self.crypter.update(&buf[..], &mut self.buffer[..])?;
self.crypter.finalize(&mut self.buffer[..n])?;
self.stream.write_all(&self.buffer[..n])
},
self.buffer.clear();
}
}
#[inline] fn flush(&mut self) -> io::Result<()> {
self.stream.flush()
}
}
#[cfg(test)]
mod tests
{
use super::*;
const INPUT: &'static str = "Hello world!";
fn enc_stream(input: impl AsRef<[u8]>, key: Key, iv: IV) -> Sink<Vec<u8>>
{
let enc_buffer = Vec::new();
let input = input.as_ref();
eprintln!("(enc) Key: {}, IV: {}, Input: ({}, {})", key, iv, input.len(), input.hex());
let mut stream = Sink::encrypt(enc_buffer, key, iv).expect("sink::enc");
assert_eq!(stream.write(input).unwrap(), input.len());
stream.flush().unwrap();
eprintln!("Output encrypted: {}", stream.inner().hex());
stream
}
#[test]
fn enc()
{
let (key, iv) = cha::keygen();
eprintln!("Sink ends: {:?}", enc_stream(INPUT.as_bytes(), key, iv));
}
#[test]
fn dec()
{
let (key, iv) = cha::keygen();
eprintln!("Input unencrypted: {}", INPUT.hex());
let input = enc_stream(INPUT.as_bytes(), key.clone(), iv.clone()).into_inner();
let mut dec_buffer = Vec::new();
{
let mut stream = Sink::decrypt(&mut dec_buffer, key, iv).expect("sink::dec");
stream.write_all(&input[..]).unwrap();
stream.flush().unwrap();
eprintln!("Output decrypted: {}", stream.inner().hex());
}
assert_eq!(&dec_buffer[..], INPUT.as_bytes());
}
}
Loading…
Cancel
Save