From 0abd878df2a2a9dc56ff0764dad7216902cc5630 Mon Sep 17 00:00:00 2001 From: Avril Date: Sat, 20 Mar 2021 00:20:50 +0000 Subject: [PATCH] initial commit --- .gitignore | 2 + Cargo.lock | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 13 ++++++ src/cha.rs | 112 ++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 48 +++++++++++++++++++ 5 files changed, 307 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 src/cha.rs create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e2a3069 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +*~ diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..a661d3a --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,132 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + +[[package]] +name = "base64" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" + +[[package]] +name = "bitflags" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" + +[[package]] +name = "cc" +version = "1.0.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chachaex" +version = "0.1.0" +dependencies = [ + "base64", + "getrandom", + "hex-literal", + "openssl", +] + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "getrandom" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "hex-literal" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5af1f635ef1bc545d78392b136bfe1c9809e029023c84a3638a864a10b8819c8" + +[[package]] +name = "libc" +version = "0.2.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba4aede83fc3617411dc6993bc8c70919750c1c257c6ca6a502aed6e0e2394ae" + +[[package]] +name = "once_cell" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3" + +[[package]] +name = "openssl" +version = "0.10.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a61075b62a23fef5a29815de7536d940aa35ce96d18ce0cc5076272db678a577" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-sys", +] + +[[package]] +name = "openssl-sys" +version = "0.9.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "313752393519e876837e09e1fa183ddef0be7735868dced3196f4472d536277f" +dependencies = [ + "autocfg", + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "pkg-config" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" + +[[package]] +name = "vcpkg" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b00bca6106a5e23f3eee943593759b7fcddb00554332e856d990c893966879fb" + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..685f9df --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "chachaex" +version = "0.1.0" +authors = ["Avril "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +base64 = "0.13.0" +getrandom = "0.2.2" +hex-literal = "0.3.1" +openssl = "0.10.32" diff --git a/src/cha.rs b/src/cha.rs new file mode 100644 index 0000000..3bf7f9a --- /dev/null +++ b/src/cha.rs @@ -0,0 +1,112 @@ + +use getrandom::getrandom; +use openssl::{ + symm::{ + Cipher, Crypter, Mode, + }, + error::ErrorStack, +}; + +pub const KEY_SIZE: usize = 32; +pub const IV_SIZE: usize = 12; + +static NEW_CIPHER: fn() -> Cipher = Cipher::chacha20_poly1305; + +#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)] +#[repr(transparent)] +pub struct Key([u8; KEY_SIZE]); + +#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)] +#[repr(transparent)] +pub struct IV([u8; IV_SIZE]); + +#[inline] pub fn decrypter(key: impl AsRef, iv: impl AsRef) -> Result +{ + Crypter::new( + NEW_CIPHER(), + Mode::Decrypt, + key.as_ref().as_ref(), + Some(iv.as_ref().as_ref()) + ) +} +#[inline] pub fn encrypter(key: impl AsRef, iv: impl AsRef) -> Result +{ + Crypter::new( + NEW_CIPHER(), + Mode::Encrypt, + key.as_ref().as_ref(), + Some(iv.as_ref().as_ref()) + ) +} + +impl Key +{ + pub fn new() -> Self + { + let mut output = [0u8; KEY_SIZE]; + getrandom(&mut output[..]).expect("rng fatal"); + Self(output) + } +} + +impl IV +{ + pub fn new() -> Self + { + let mut output = [0u8; IV_SIZE]; + getrandom(&mut output[..]).expect("rng fatal"); + Self(output) + } +} + +impl AsRef<[u8]> for Key +{ + fn as_ref(&self) -> &[u8] + { + &self.0[..] + } +} +impl AsRef<[u8]> for IV +{ + fn as_ref(&self) -> &[u8] + { + &self.0[..] + } +} + +impl AsMut<[u8]> for Key +{ + fn as_mut(&mut self) -> &mut [u8] + { + &mut self.0[..] + } +} + +impl AsMut<[u8]> for IV +{ + fn as_mut(&mut self) -> &mut [u8] + { + &mut self.0[..] + } +} + +#[inline(always)] pub fn keygen() -> (Key, IV) +{ + (Key::new(), IV::new()) +} + +impl AsRef for Key +{ + #[inline] fn as_ref(&self) -> &Key + { + self + } +} +impl AsRef for IV +{ + #[inline] fn as_ref(&self) -> &IV + { + self + } +} + diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..abc9b91 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,48 @@ + +#[macro_use] extern crate hex_literal; + +mod cha; + +use cha::{Key, IV}; + +fn encrypt((key, iv): &(Key, IV), input: impl Into>) -> Result +{ + let input = input.into();//.into(); + let mut output = vec![0u8; input.len()]; + + eprintln!("(enc) Key: {:?}, IV: {:?}, Input: ({}, {:?})", key, iv, input.len(), input); + + let mut enc = cha::encrypter(key, iv)?; + + let n = enc.update(&input[..], &mut output[..])?; + eprintln!("(enc) Written {} bytes", n); + enc.finalize(&mut output[..n])?; + + Ok(base64::encode(&output[..n])) +} + +fn decrypt((key, iv): &(Key, IV), input: impl Into) -> Result, openssl::error::ErrorStack> +{ + let input = base64::decode(input.into()).expect("invalid base64"); + let mut output = vec![0u8; input.len()]; + + eprintln!("(dec) Key: {:?}, IV: {:?}, Input: ({}, {:?})", key, iv, input.len(), input); + + let mut dec = cha::decrypter(key, iv)?; + + let n = dec.update(&input[..], &mut output[..])?; + eprintln!("(dec) Written {} bytes", n); + dec.finalize(&mut output[..n])?; + + output.truncate(n); + Ok(output) +} + +fn main() { + let key = cha::keygen(); + let enc = encrypt(&key, std::env::args().nth(1).unwrap()).expect("encrypt"); + println!("{}", enc); + let dec = decrypt(&key, enc).expect("decrypt"); + + println!("{:?}", std::str::from_utf8(&dec[..]).unwrap()); +}