From 3445114aeb38efc7a51ee702ab11dd5db0734740 Mon Sep 17 00:00:00 2001 From: Anjan Roy Date: Mon, 16 May 2022 08:39:57 +0530 Subject: [PATCH 01/11] thin c-wrapper on top of c++ harpocrates implementation Signed-off-by: Anjan Roy --- wrapper/harpocrates.cpp | 59 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 wrapper/harpocrates.cpp diff --git a/wrapper/harpocrates.cpp b/wrapper/harpocrates.cpp new file mode 100644 index 0000000..38462e7 --- /dev/null +++ b/wrapper/harpocrates.cpp @@ -0,0 +1,59 @@ +#include "harpocrates.hpp" + +// Thin C wrapper on top of underlying C++ implementation of Harpocrates Cipher, +// which can be used for producing shared library object with C-ABI & used from +// other languages such as Rust, Python + +// Function declarations +extern "C" +{ + void encrypt(const uint8_t* const __restrict, + const uint8_t* const __restrict, + uint8_t* const __restrict); + + void decrypt(const uint8_t* const __restrict, + const uint8_t* const __restrict, + uint8_t* const __restrict); +} + +// Function implementations +extern "C" +{ + // Given 256 -bytes look up table, 16 -bytes plain text, this routine computes + // 16 -bytes encrypted data using Harpocrates encryption algorithm + // + // Input: + // + // - lut: 256 -bytes of look up table i.e. len(lut) == 256 + // - txt: 16 -bytes plain text i.e. len(txt) == 16 + // + // Output: + // + // - enc: 16 -bytes of encrypted data i.e. len(enc) == 16 + void encrypt(const uint8_t* const __restrict lut, + const uint8_t* const __restrict txt, + uint8_t* const __restrict enc) + { + + harpocrates::encrypt(lut, txt, enc); + } + + // Given 256 -bytes inverse look up table, 16 -bytes encrypted data, this + // routine computes 16 -bytes decrypted data using Harpocrates decryption + // algorithm + // + // Input: + // + // - ilut: 256 -bytes of inverse look up table i.e. len(ilut) == 256 + // - enc: 16 -bytes encrypted text i.e. len(enc) == 16 + // + // Output: + // + // - dec: 16 -bytes of decrypted data i.e. len(dec) == 16 + void decrypt(const uint8_t* const __restrict ilut, + const uint8_t* const __restrict enc, + uint8_t* const __restrict dec) + { + harpocrates::decrypt(ilut, enc, dec); + } +} From 692cb94db7e86cb139b40ee1fd10e14f0964b688 Mon Sep 17 00:00:00 2001 From: Anjan Roy Date: Mon, 16 May 2022 08:40:54 +0530 Subject: [PATCH 02/11] make recipe for easily building shared library object Signed-off-by: Anjan Roy --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index b8a7d5f..318162e 100644 --- a/Makefile +++ b/Makefile @@ -19,6 +19,9 @@ clean: format: find . -name '*.cpp' -o -name '*.hpp' | xargs clang-format -i --style=Mozilla +lib: + $(CXX) $(CXXFLAGS) $(OPTFLAGS) $(IFLAGS) -fPIC --shared wrapper/harpocrates.cpp -o wrapper/libharpocrates.so + # benchmarks Harpocrates minimal cipher variant on CPU bench/harpocrates.out: bench/harpocrates.cpp include/*.hpp $(CXX) $(CXXFLAGS) $(OPTFLAGS) $(IFLAGS) $< -lbenchmark -o $@ From d7ba2b6d1e35d12330283756d6fb1d06e9bcb1f7 Mon Sep 17 00:00:00 2001 From: Anjan Roy Date: Mon, 16 May 2022 09:14:22 +0530 Subject: [PATCH 03/11] added functions for generating (inverse) look up table Signed-off-by: Anjan Roy --- wrapper/harpocrates.cpp | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/wrapper/harpocrates.cpp b/wrapper/harpocrates.cpp index 38462e7..4b0a7b9 100644 --- a/wrapper/harpocrates.cpp +++ b/wrapper/harpocrates.cpp @@ -7,6 +7,11 @@ // Function declarations extern "C" { + void generate_lut(uint8_t* const); + + void generate_ilut(const uint8_t* const __restrict, + uint8_t* const __restrict); + void encrypt(const uint8_t* const __restrict, const uint8_t* const __restrict, uint8_t* const __restrict); @@ -19,6 +24,28 @@ extern "C" // Function implementations extern "C" { + // Generates Harpocrates look up table which is used during encryption. + // Inverse look up table is also computed from it, which is used during + // decryption. + // + // This function is used only during setup phase. Size of look up table is 256 + // -bytes. + void generate_lut(uint8_t* const lut) + { + harpocrates_utils::generate_lut(lut); + } + + // Computes Harpocrates inverse look up table from already generated look up + // table. + // + // This function is used only during setup phase. Size of (inverse) look up + // table is 256 -bytes. + void generate_ilut(const uint8_t* const __restrict lut, + uint8_t* const __restrict ilut) + { + harpocrates_utils::generate_inv_lut(lut, ilut); + } + // Given 256 -bytes look up table, 16 -bytes plain text, this routine computes // 16 -bytes encrypted data using Harpocrates encryption algorithm // From 16f35cc0ba2beeb3a14ce353d93fa5c5c894ecf6 Mon Sep 17 00:00:00 2001 From: Anjan Roy Date: Mon, 16 May 2022 09:57:06 +0530 Subject: [PATCH 04/11] safe rust interface over unsafe c++ harpocrates cipher implementation Signed-off-by: Anjan Roy --- .gitignore | 1 + wrapper/harpocrates.cpp | 36 +++++++++++------------ wrapper/rust/Cargo.lock | 7 +++++ wrapper/rust/Cargo.toml | 6 ++++ wrapper/rust/build.rs | 4 +++ wrapper/rust/src/harpocrates.rs | 51 +++++++++++++++++++++++++++++++++ wrapper/rust/src/main.rs | 28 ++++++++++++++++++ 7 files changed, 115 insertions(+), 18 deletions(-) create mode 100644 wrapper/rust/Cargo.lock create mode 100644 wrapper/rust/Cargo.toml create mode 100644 wrapper/rust/build.rs create mode 100644 wrapper/rust/src/harpocrates.rs create mode 100644 wrapper/rust/src/main.rs diff --git a/.gitignore b/.gitignore index e966b79..7626ae1 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ *.so *.a *.o +wrapper/rust/target diff --git a/wrapper/harpocrates.cpp b/wrapper/harpocrates.cpp index 4b0a7b9..9292392 100644 --- a/wrapper/harpocrates.cpp +++ b/wrapper/harpocrates.cpp @@ -7,18 +7,18 @@ // Function declarations extern "C" { - void generate_lut(uint8_t* const); + void generate_harpocrates_lut(uint8_t* const); - void generate_ilut(const uint8_t* const __restrict, - uint8_t* const __restrict); + void generate_harpocrates_ilut(const uint8_t* const __restrict, + uint8_t* const __restrict); - void encrypt(const uint8_t* const __restrict, - const uint8_t* const __restrict, - uint8_t* const __restrict); + void harpocrates_encrypt(const uint8_t* const __restrict, + const uint8_t* const __restrict, + uint8_t* const __restrict); - void decrypt(const uint8_t* const __restrict, - const uint8_t* const __restrict, - uint8_t* const __restrict); + void harpocrates_decrypt(const uint8_t* const __restrict, + const uint8_t* const __restrict, + uint8_t* const __restrict); } // Function implementations @@ -30,7 +30,7 @@ extern "C" // // This function is used only during setup phase. Size of look up table is 256 // -bytes. - void generate_lut(uint8_t* const lut) + void generate_harpocrates_lut(uint8_t* const lut) { harpocrates_utils::generate_lut(lut); } @@ -40,8 +40,8 @@ extern "C" // // This function is used only during setup phase. Size of (inverse) look up // table is 256 -bytes. - void generate_ilut(const uint8_t* const __restrict lut, - uint8_t* const __restrict ilut) + void generate_harpocrates_ilut(const uint8_t* const __restrict lut, + uint8_t* const __restrict ilut) { harpocrates_utils::generate_inv_lut(lut, ilut); } @@ -57,9 +57,9 @@ extern "C" // Output: // // - enc: 16 -bytes of encrypted data i.e. len(enc) == 16 - void encrypt(const uint8_t* const __restrict lut, - const uint8_t* const __restrict txt, - uint8_t* const __restrict enc) + void harpocrates_encrypt(const uint8_t* const __restrict lut, + const uint8_t* const __restrict txt, + uint8_t* const __restrict enc) { harpocrates::encrypt(lut, txt, enc); @@ -77,9 +77,9 @@ extern "C" // Output: // // - dec: 16 -bytes of decrypted data i.e. len(dec) == 16 - void decrypt(const uint8_t* const __restrict ilut, - const uint8_t* const __restrict enc, - uint8_t* const __restrict dec) + void harpocrates_decrypt(const uint8_t* const __restrict ilut, + const uint8_t* const __restrict enc, + uint8_t* const __restrict dec) { harpocrates::decrypt(ilut, enc, dec); } diff --git a/wrapper/rust/Cargo.lock b/wrapper/rust/Cargo.lock new file mode 100644 index 0000000..f26ecba --- /dev/null +++ b/wrapper/rust/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "harpocrates" +version = "0.1.0" diff --git a/wrapper/rust/Cargo.toml b/wrapper/rust/Cargo.toml new file mode 100644 index 0000000..088d219 --- /dev/null +++ b/wrapper/rust/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "harpocrates" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/wrapper/rust/build.rs b/wrapper/rust/build.rs new file mode 100644 index 0000000..79f2bd4 --- /dev/null +++ b/wrapper/rust/build.rs @@ -0,0 +1,4 @@ +fn main() { + println!("cargo:rustc-link-search=native=.."); + println!("cargo:rustc-link-lib=dylib=harpocrates"); +} diff --git a/wrapper/rust/src/harpocrates.rs b/wrapper/rust/src/harpocrates.rs new file mode 100644 index 0000000..785c0d7 --- /dev/null +++ b/wrapper/rust/src/harpocrates.rs @@ -0,0 +1,51 @@ +extern "C" { + fn generate_harpocrates_lut(lut: *mut u8); + fn generate_harpocrates_ilut(lut: *const u8, ilut: *mut u8); + fn harpocrates_encrypt(lut: *const u8, txt: *const u8, enc: *mut u8); + fn harpocrates_decrypt(ilut: *const u8, enc: *const u8, dec: *mut u8); +} + +/// Generates Harpocrates look up table of size 256 -bytes +/// +/// Ensure that len(lut) == 256 +pub fn generate_lut(lut: &mut [u8]) { + assert_eq!(lut.len(), 256); + unsafe { + generate_harpocrates_lut(lut.as_mut_ptr()); + } +} + +/// Computes Harpocrates inverse look up table of size 256 -bytes, from equal sized look up table +/// +/// Ensure that len(lut) == len(ilut) == 256 +pub fn generate_ilut(lut: &[u8], ilut: &mut [u8]) { + assert_eq!(lut.len(), 256); + assert_eq!(ilut.len(), 256); + unsafe { + generate_harpocrates_ilut(lut.as_ptr(), ilut.as_mut_ptr()); + } +} + +/// Given 256 -bytes look up table & 16 -bytes plain text, this routine computes 16 -bytes cipher data +/// +/// Ensure that len(lut) == 256 && len(txt) == len(enc) == 16 +pub fn encrypt(lut: &[u8], txt: &[u8], enc: &mut [u8]) { + assert_eq!(lut.len(), 256); + assert_eq!(txt.len(), 16); + assert_eq!(enc.len(), 16); + unsafe { + harpocrates_encrypt(lut.as_ptr(), txt.as_ptr(), enc.as_mut_ptr()); + } +} + +/// Given 256 -bytes inverse look up table & 16 -bytes encrypted data, this routine computes 16 -bytes decrypted data +/// +/// Ensure that len(ilut) == 256 && len(enc) == len(dec) == 16 +pub fn decrypt(ilut: &[u8], enc: &[u8], dec: &mut [u8]) { + assert_eq!(ilut.len(), 256); + assert_eq!(enc.len(), 16); + assert_eq!(dec.len(), 16); + unsafe { + harpocrates_decrypt(ilut.as_ptr(), enc.as_ptr(), dec.as_mut_ptr()); + } +} diff --git a/wrapper/rust/src/main.rs b/wrapper/rust/src/main.rs new file mode 100644 index 0000000..c59e9ee --- /dev/null +++ b/wrapper/rust/src/main.rs @@ -0,0 +1,28 @@ +mod harpocrates; + +fn main() { + let mut lut = [0u8; 256]; + let mut ilut = [0u8; 256]; + + let mut txt = Vec::::with_capacity(16); + let mut enc = Vec::::with_capacity(16); + let mut dec = Vec::::with_capacity(16); + + unsafe { + txt.set_len(16); + enc.set_len(16); + dec.set_len(16); + } + + txt.fill(0xffu8); + + harpocrates::generate_lut(&mut lut); + harpocrates::generate_ilut(&lut, &mut ilut); + + harpocrates::encrypt(&lut, &txt, &mut enc); + harpocrates::decrypt(&ilut, &enc, &mut dec); + + println!("Text = {:x?}", txt); + println!("Encrypted = {:x?}", enc); + println!("Decrypted = {:x?}", dec); +} From 3d6d030aa43e68a589610737e0f16b6acd1ea999 Mon Sep 17 00:00:00 2001 From: Anjan Roy Date: Mon, 16 May 2022 10:51:22 +0530 Subject: [PATCH 05/11] test harpocrates wrapper API Signed-off-by: Anjan Roy --- wrapper/rust/Cargo.lock | 652 ++++++++++++++++++++++++++++++++ wrapper/rust/Cargo.toml | 8 + wrapper/rust/src/harpocrates.rs | 38 ++ wrapper/rust/src/lib.rs | 1 + wrapper/rust/src/main.rs | 28 -- 5 files changed, 699 insertions(+), 28 deletions(-) create mode 100644 wrapper/rust/src/lib.rs delete mode 100644 wrapper/rust/src/main.rs diff --git a/wrapper/rust/Cargo.lock b/wrapper/rust/Cargo.lock index f26ecba..731843f 100644 --- a/wrapper/rust/Cargo.lock +++ b/wrapper/rust/Cargo.lock @@ -2,6 +2,658 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bstr" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" +dependencies = [ + "lazy_static", + "memchr", + "regex-automata", + "serde", +] + +[[package]] +name = "bumpalo" +version = "3.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" + +[[package]] +name = "cast" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c24dab4283a142afa2fdca129b80ad2c6284e073930f964c3a1293c225ee39a" +dependencies = [ + "rustc_version", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clap" +version = "2.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +dependencies = [ + "bitflags", + "textwrap", + "unicode-width", +] + +[[package]] +name = "criterion" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1604dafd25fba2fe2d5895a9da139f8dc9b319a5fe5354ca137cbbce4e178d10" +dependencies = [ + "atty", + "cast", + "clap", + "criterion-plot", + "csv", + "itertools", + "lazy_static", + "num-traits", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_cbor", + "serde_derive", + "serde_json", + "tinytemplate", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d00996de9f2f7559f7f4dc286073197f83e92256a59ed395f9aac01fe717da57" +dependencies = [ + "cast", + "itertools", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1145cf131a2c6ba0615079ab6a638f7e1973ac9c2634fcbeaaad6114246efe8c" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "lazy_static", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" +dependencies = [ + "cfg-if", + "lazy_static", +] + +[[package]] +name = "csv" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1" +dependencies = [ + "bstr", + "csv-core", + "itoa 0.4.8", + "ryu", + "serde", +] + +[[package]] +name = "csv-core" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" +dependencies = [ + "memchr", +] + +[[package]] +name = "either" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" + +[[package]] +name = "getrandom" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "half" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" + [[package]] name = "harpocrates" version = "0.1.0" +dependencies = [ + "criterion", + "rand", +] + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "itertools" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" + +[[package]] +name = "itoa" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" + +[[package]] +name = "js-sys" +version = "0.3.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "671a26f820db17c2a2750743f1dd03bafd15b98c9f30c7c2628c024c05d73397" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.125" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5916d2ae698f6de9bfb891ad7a8d65c09d232dc58cc4ac433c7da3b2fd84bc2b" + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "oorandom" +version = "11.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" + +[[package]] +name = "plotters" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a3fd9ec30b9749ce28cd91f255d569591cdf937fe280c312143e3c4bad6f2a" +dependencies = [ + "num-traits", + "plotters-backend", + "plotters-svg", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "plotters-backend" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d88417318da0eaf0fdcdb51a0ee6c3bed624333bff8f946733049380be67ac1c" + +[[package]] +name = "plotters-svg" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521fa9638fa597e1dc53e9412a4f9cefb01187ee1f7413076f9e6749e2885ba9" +dependencies = [ + "plotters-backend", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" + +[[package]] +name = "proc-macro2" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9027b48e9d4c9175fa2218adf3557f91c1137021739951d4932f5f8268ac48aa" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rayon" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" +dependencies = [ + "autocfg", + "crossbeam-deque", + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "num_cpus", +] + +[[package]] +name = "regex" +version = "1.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" +dependencies = [ + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" + +[[package]] +name = "regex-syntax" +version = "0.6.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "ryu" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "semver" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cb243bdfdb5936c8dc3c45762a19d12ab4550cdc753bc247637d4ec35a040fd" + +[[package]] +name = "serde" +version = "1.0.137" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" + +[[package]] +name = "serde_cbor" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" +dependencies = [ + "half", + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.137" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c" +dependencies = [ + "itoa 1.0.2", + "ryu", + "serde", +] + +[[package]] +name = "syn" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a07e33e919ebcd69113d5be0e4d70c5707004ff45188910106854f38b960df4a" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "tinytemplate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "unicode-width" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" + +[[package]] +name = "unicode-xid" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" + +[[package]] +name = "walkdir" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +dependencies = [ + "same-file", + "winapi", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + +[[package]] +name = "wasm-bindgen" +version = "0.2.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27370197c907c55e3f1a9fbe26f44e937fe6451368324e009cba39e139dc08ad" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53e04185bfa3a779273da532f5025e33398409573f348985af9a1cbf3774d3f4" +dependencies = [ + "bumpalo", + "lazy_static", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d554b7f530dee5964d9a9468d95c1f8b8acae4f282807e7d27d4b03099a46744" + +[[package]] +name = "web-sys" +version = "0.3.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b17e741662c70c8bd24ac5c5b18de314a2c26c32bf8346ee1e6f53de919c283" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/wrapper/rust/Cargo.toml b/wrapper/rust/Cargo.toml index 088d219..6b3bf4e 100644 --- a/wrapper/rust/Cargo.toml +++ b/wrapper/rust/Cargo.toml @@ -4,3 +4,11 @@ version = "0.1.0" edition = "2021" [dependencies] + +[dev-dependencies] +rand = "0.8.4" +criterion = "0.3.5" + +[[bench]] +name = "harpocrates" +harness = false diff --git a/wrapper/rust/src/harpocrates.rs b/wrapper/rust/src/harpocrates.rs index 785c0d7..97bfbce 100644 --- a/wrapper/rust/src/harpocrates.rs +++ b/wrapper/rust/src/harpocrates.rs @@ -49,3 +49,41 @@ pub fn decrypt(ilut: &[u8], enc: &[u8], dec: &mut [u8]) { harpocrates_decrypt(ilut.as_ptr(), enc.as_ptr(), dec.as_mut_ptr()); } } + +mod test { + #[test] + fn harpocrates_cipher() { + use crate::harpocrates::*; + use rand::prelude::*; + + let mut lut = Vec::::with_capacity(256); + let mut ilut = Vec::::with_capacity(256); + let mut txt = Vec::::with_capacity(16); + let mut enc = Vec::::with_capacity(16); + let mut dec = Vec::::with_capacity(16); + + unsafe { + lut.set_len(256); + ilut.set_len(256); + txt.set_len(16); + enc.set_len(16); + dec.set_len(16); + } + + generate_lut(&mut lut); + generate_ilut(&lut, &mut ilut); + + let mut rng = thread_rng(); + + rng.fill_bytes(&mut txt); + enc.fill(0u8); + dec.fill(0u8); + + encrypt(&lut, &txt, &mut enc); + decrypt(&ilut, &enc, &mut dec); + + for i in 0..16 { + assert_eq!(txt[i], dec[i]); + } + } +} diff --git a/wrapper/rust/src/lib.rs b/wrapper/rust/src/lib.rs new file mode 100644 index 0000000..77a3295 --- /dev/null +++ b/wrapper/rust/src/lib.rs @@ -0,0 +1 @@ +pub mod harpocrates; diff --git a/wrapper/rust/src/main.rs b/wrapper/rust/src/main.rs deleted file mode 100644 index c59e9ee..0000000 --- a/wrapper/rust/src/main.rs +++ /dev/null @@ -1,28 +0,0 @@ -mod harpocrates; - -fn main() { - let mut lut = [0u8; 256]; - let mut ilut = [0u8; 256]; - - let mut txt = Vec::::with_capacity(16); - let mut enc = Vec::::with_capacity(16); - let mut dec = Vec::::with_capacity(16); - - unsafe { - txt.set_len(16); - enc.set_len(16); - dec.set_len(16); - } - - txt.fill(0xffu8); - - harpocrates::generate_lut(&mut lut); - harpocrates::generate_ilut(&lut, &mut ilut); - - harpocrates::encrypt(&lut, &txt, &mut enc); - harpocrates::decrypt(&ilut, &enc, &mut dec); - - println!("Text = {:x?}", txt); - println!("Encrypted = {:x?}", enc); - println!("Decrypted = {:x?}", dec); -} From 3e7a52361547032f6e9c82f00abfabad32afcf47 Mon Sep 17 00:00:00 2001 From: Anjan Roy Date: Mon, 16 May 2022 11:07:24 +0530 Subject: [PATCH 06/11] benchmark rust wrapper API of harpocrates Signed-off-by: Anjan Roy --- wrapper/rust/benches/harpocrates.rs | 44 +++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 wrapper/rust/benches/harpocrates.rs diff --git a/wrapper/rust/benches/harpocrates.rs b/wrapper/rust/benches/harpocrates.rs new file mode 100644 index 0000000..ede45bb --- /dev/null +++ b/wrapper/rust/benches/harpocrates.rs @@ -0,0 +1,44 @@ +extern crate criterion; + +use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use harpocrates::harpocrates::{decrypt, encrypt, generate_ilut, generate_lut}; +use rand::prelude::*; + +fn bench_harpocrates(c: &mut Criterion) { + let mut lut = [0u8; 256]; + let mut ilut = [0u8; 256]; + + let mut txt = Vec::::with_capacity(16); + let mut enc = Vec::::with_capacity(16); + let mut dec = Vec::::with_capacity(16); + + unsafe { + txt.set_len(16); + enc.set_len(16); + dec.set_len(16); + } + + generate_lut(&mut lut); + generate_ilut(&lut, &mut ilut); + + let mut rng = thread_rng(); + + rng.fill_bytes(&mut txt); + enc.fill(0u8); + dec.fill(0u8); + + c.bench_function("harpocrates_encrypt", |b| { + b.iter(|| { + encrypt(black_box(&lut), black_box(&txt), black_box(&mut enc)); + }); + }); + + c.bench_function("harpocrates_decrypt", |b| { + b.iter(|| { + decrypt(black_box(&ilut), black_box(&enc), black_box(&mut dec)); + }); + }); +} + +criterion_group!(harpocrates, bench_harpocrates); +criterion_main!(harpocrates); From 65e74e9044f69162bb7a98a73b9636b3c162ab63 Mon Sep 17 00:00:00 2001 From: Anjan Roy Date: Mon, 16 May 2022 11:39:38 +0530 Subject: [PATCH 07/11] encrypt/ decrypt N -bytes slice | N & 15 == 0; added test cases Signed-off-by: Anjan Roy --- wrapper/rust/Cargo.lock | 7 +++ wrapper/rust/Cargo.toml | 1 + wrapper/rust/src/harpocrates.rs | 98 +++++++++++++++++++++++++++++++-- wrapper/rust/src/lib.rs | 1 + 4 files changed, 101 insertions(+), 6 deletions(-) diff --git a/wrapper/rust/Cargo.lock b/wrapper/rust/Cargo.lock index 731843f..94bf02e 100644 --- a/wrapper/rust/Cargo.lock +++ b/wrapper/rust/Cargo.lock @@ -201,6 +201,7 @@ version = "0.1.0" dependencies = [ "criterion", "rand", + "static_assertions", ] [[package]] @@ -504,6 +505,12 @@ dependencies = [ "serde", ] +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "syn" version = "1.0.94" diff --git a/wrapper/rust/Cargo.toml b/wrapper/rust/Cargo.toml index 6b3bf4e..32d9eb3 100644 --- a/wrapper/rust/Cargo.toml +++ b/wrapper/rust/Cargo.toml @@ -4,6 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] +static_assertions = "1.1.0" [dev-dependencies] rand = "0.8.4" diff --git a/wrapper/rust/src/harpocrates.rs b/wrapper/rust/src/harpocrates.rs index 97bfbce..1d327d3 100644 --- a/wrapper/rust/src/harpocrates.rs +++ b/wrapper/rust/src/harpocrates.rs @@ -7,7 +7,7 @@ extern "C" { /// Generates Harpocrates look up table of size 256 -bytes /// -/// Ensure that len(lut) == 256 +/// Ensure that `len(lut) == 256` pub fn generate_lut(lut: &mut [u8]) { assert_eq!(lut.len(), 256); unsafe { @@ -17,7 +17,7 @@ pub fn generate_lut(lut: &mut [u8]) { /// Computes Harpocrates inverse look up table of size 256 -bytes, from equal sized look up table /// -/// Ensure that len(lut) == len(ilut) == 256 +/// Ensure that `len(lut) == len(ilut) == 256` pub fn generate_ilut(lut: &[u8], ilut: &mut [u8]) { assert_eq!(lut.len(), 256); assert_eq!(ilut.len(), 256); @@ -26,9 +26,10 @@ pub fn generate_ilut(lut: &[u8], ilut: &mut [u8]) { } } -/// Given 256 -bytes look up table & 16 -bytes plain text, this routine computes 16 -bytes cipher data +/// Given 256 -bytes look up table & 16 -bytes plain text, this routine +/// computes 16 -bytes cipher data /// -/// Ensure that len(lut) == 256 && len(txt) == len(enc) == 16 +/// Ensure that `len(lut) == 256 && len(txt) == len(enc) == 16` pub fn encrypt(lut: &[u8], txt: &[u8], enc: &mut [u8]) { assert_eq!(lut.len(), 256); assert_eq!(txt.len(), 16); @@ -38,9 +39,10 @@ pub fn encrypt(lut: &[u8], txt: &[u8], enc: &mut [u8]) { } } -/// Given 256 -bytes inverse look up table & 16 -bytes encrypted data, this routine computes 16 -bytes decrypted data +/// Given 256 -bytes inverse look up table & 16 -bytes encrypted data, +/// this routine computes 16 -bytes decrypted data /// -/// Ensure that len(ilut) == 256 && len(enc) == len(dec) == 16 +/// Ensure that `len(ilut) == 256 && len(enc) == len(dec) == 16` pub fn decrypt(ilut: &[u8], enc: &[u8], dec: &mut [u8]) { assert_eq!(ilut.len(), 256); assert_eq!(enc.len(), 16); @@ -50,6 +52,50 @@ pub fn decrypt(ilut: &[u8], enc: &[u8], dec: &mut [u8]) { } } +/// Given 256 -bytes look up table & N -bytes plain text such that N is evenly +/// divisible by 16 ( so that each 16 -bytes slice can be encrypted by calling +/// `encrypt` routine ), this function computes N -bytes encrypted data +/// by invoking `encrypt` routine ( see above ) (N >> 4) -many times +/// +/// Ensure that `len(lut) == 256 && len(txt) == len(enc) == N && N & 15 == 0` +pub fn encrypt_data(lut: &[u8], txt: &[u8], enc: &mut [u8]) { + let ct_len = txt.len(); + let chunks = ct_len >> 4; + + assert_eq!(lut.len(), 256); + assert_eq!(ct_len, enc.len()); + assert_eq!(ct_len & 15, 0); + + for c in 0..chunks { + let frm = c << 4; + let to = (c + 1) << 4; + + encrypt(lut, &txt[frm..to], &mut enc[frm..to]); + } +} + +/// Given 256 -bytes inverse look up table & N -bytes cipher text such that N is evenly +/// divisible by 16 ( so that each 16 -bytes slice can be decrypted by calling +/// `decrypt` routine ), this function computes N -bytes decrypted data +/// by invoking `decrypt` routine ( see above ) (N >> 4) -many times +/// +/// Ensure that `len(ilut) == 256 && len(enc) == len(dec) == N && N & 15 == 0` +pub fn decrypt_data(ilut: &[u8], enc: &[u8], dec: &mut [u8]) { + let ct_len = enc.len(); + let chunks = ct_len >> 4; + + assert_eq!(ilut.len(), 256); + assert_eq!(ct_len, dec.len()); + assert_eq!(ct_len & 15, 0); + + for c in 0..chunks { + let frm = c << 4; + let to = (c + 1) << 4; + + decrypt(ilut, &enc[frm..to], &mut dec[frm..to]); + } +} + mod test { #[test] fn harpocrates_cipher() { @@ -86,4 +132,44 @@ mod test { assert_eq!(txt[i], dec[i]); } } + + #[test] + fn harpocrates_cipher_with_large_data_block() { + use crate::harpocrates::*; + use rand::prelude::*; + use static_assertions::const_assert; + + const CT_LEN: usize = 1 << 20; + const_assert!(CT_LEN & 15 == 0); + + let mut lut = Vec::::with_capacity(256); + let mut ilut = Vec::::with_capacity(256); + let mut txt = Vec::::with_capacity(CT_LEN); + let mut enc = Vec::::with_capacity(CT_LEN); + let mut dec = Vec::::with_capacity(CT_LEN); + + unsafe { + lut.set_len(256); + ilut.set_len(256); + txt.set_len(CT_LEN); + enc.set_len(CT_LEN); + dec.set_len(CT_LEN); + } + + generate_lut(&mut lut); + generate_ilut(&lut, &mut ilut); + + let mut rng = thread_rng(); + + rng.fill_bytes(&mut txt); + enc.fill(0u8); + dec.fill(0u8); + + encrypt_data(&lut, &txt, &mut enc); + decrypt_data(&ilut, &enc, &mut dec); + + for i in 0..CT_LEN { + assert_eq!(txt[i], dec[i]); + } + } } diff --git a/wrapper/rust/src/lib.rs b/wrapper/rust/src/lib.rs index 77a3295..4e9fd31 100644 --- a/wrapper/rust/src/lib.rs +++ b/wrapper/rust/src/lib.rs @@ -1 +1,2 @@ +extern crate static_assertions; pub mod harpocrates; From ab7cf386a8ddd6f804df027f7921228da30fd431 Mon Sep 17 00:00:00 2001 From: Anjan Roy Date: Mon, 16 May 2022 11:40:35 +0530 Subject: [PATCH 08/11] test/ benchmark rust wrapper API easily, added makefile recipes Signed-off-by: Anjan Roy --- Makefile | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Makefile b/Makefile index 318162e..80c98ee 100644 --- a/Makefile +++ b/Makefile @@ -22,6 +22,12 @@ format: lib: $(CXX) $(CXXFLAGS) $(OPTFLAGS) $(IFLAGS) -fPIC --shared wrapper/harpocrates.cpp -o wrapper/libharpocrates.so +test_rust: + make lib && cd wrapper/rust && LD_LIBRARY_PATH=.. cargo test --lib && cd ../.. + +bench_rust: + make lib && cd wrapper/rust && LD_LIBRARY_PATH=.. cargo criterion --output-format verbose && cd ../.. + # benchmarks Harpocrates minimal cipher variant on CPU bench/harpocrates.out: bench/harpocrates.cpp include/*.hpp $(CXX) $(CXXFLAGS) $(OPTFLAGS) $(IFLAGS) $< -lbenchmark -o $@ From 8a310a58ab5594c1730fe430f9c3207331afa039 Mon Sep 17 00:00:00 2001 From: Anjan Roy Date: Mon, 16 May 2022 12:10:51 +0530 Subject: [PATCH 09/11] parallelly encrypt/ decrypt N -bytes slice | N & 15 == 0; added test cases Signed-off-by: Anjan Roy --- wrapper/rust/Cargo.lock | 1 + wrapper/rust/Cargo.toml | 1 + wrapper/rust/src/harpocrates.rs | 92 +++++++++++++++++++++++++++++++++ wrapper/rust/src/lib.rs | 2 + 4 files changed, 96 insertions(+) diff --git a/wrapper/rust/Cargo.lock b/wrapper/rust/Cargo.lock index 94bf02e..8aa6ad5 100644 --- a/wrapper/rust/Cargo.lock +++ b/wrapper/rust/Cargo.lock @@ -201,6 +201,7 @@ version = "0.1.0" dependencies = [ "criterion", "rand", + "rayon", "static_assertions", ] diff --git a/wrapper/rust/Cargo.toml b/wrapper/rust/Cargo.toml index 32d9eb3..482b6ae 100644 --- a/wrapper/rust/Cargo.toml +++ b/wrapper/rust/Cargo.toml @@ -5,6 +5,7 @@ edition = "2021" [dependencies] static_assertions = "1.1.0" +rayon = "1.5.3" [dev-dependencies] rand = "0.8.4" diff --git a/wrapper/rust/src/harpocrates.rs b/wrapper/rust/src/harpocrates.rs index 1d327d3..f763763 100644 --- a/wrapper/rust/src/harpocrates.rs +++ b/wrapper/rust/src/harpocrates.rs @@ -96,6 +96,52 @@ pub fn decrypt_data(ilut: &[u8], enc: &[u8], dec: &mut [u8]) { } } +/// Given 256 -bytes look up table & N -bytes plain text such that N is evenly +/// divisible by 16 ( so that each 16 -bytes slice can independently be encrypted +/// by calling `encrypt` routine ), this function computes N -bytes encrypted data +/// by parallelly invoking `encrypt` routine ( see above ) (N >> 4) -many times +/// +/// Ensure that `len(lut) == 256 && len(txt) == len(enc) == N && N & 15 == 0` +pub fn par_encrypt_data(lut: &[u8], txt: &[u8], enc: &mut [u8]) { + use rayon::prelude::*; + + let ct_len = txt.len(); + + assert_eq!(lut.len(), 256); + assert_eq!(ct_len, enc.len()); + assert_eq!(ct_len & 15, 0); + + txt.par_chunks_exact(16) + .zip(enc.par_chunks_exact_mut(16)) + .into_par_iter() + .for_each(|(src, dst)| { + encrypt(lut, src, dst); + }); +} + +/// Given 256 -bytes inverse look up table & N -bytes cipher text such that N is evenly +/// divisible by 16 ( so that each 16 -bytes slice can independently be decrypted +/// by calling `decrypt` routine ), this function computes N -bytes decrypted data +/// by parallelly invoking `decrypt` routine ( see above ) (N >> 4) -many times +/// +/// Ensure that `len(ilut) == 256 && len(enc) == len(dec) == N && N & 15 == 0` +pub fn par_decrypt_data(ilut: &[u8], enc: &[u8], dec: &mut [u8]) { + use rayon::prelude::*; + + let ct_len = enc.len(); + + assert_eq!(ilut.len(), 256); + assert_eq!(ct_len, dec.len()); + assert_eq!(ct_len & 15, 0); + + enc.par_chunks_exact(16) + .zip(dec.par_chunks_exact_mut(16)) + .into_par_iter() + .for_each(|(src, dst)| { + decrypt(ilut, src, dst); + }); +} + mod test { #[test] fn harpocrates_cipher() { @@ -172,4 +218,50 @@ mod test { assert_eq!(txt[i], dec[i]); } } + + #[test] + fn par_harpocrates_cipher_with_large_data_block() { + use crate::harpocrates::*; + use rand::prelude::*; + use rayon::prelude::*; + use static_assertions::const_assert; + use std::sync::atomic::{AtomicBool, Ordering}; + + const CT_LEN: usize = 1 << 20; + const_assert!(CT_LEN & 15 == 0); + + let mut lut = Vec::::with_capacity(256); + let mut ilut = Vec::::with_capacity(256); + let mut txt = Vec::::with_capacity(CT_LEN); + let mut enc = Vec::::with_capacity(CT_LEN); + let mut dec = Vec::::with_capacity(CT_LEN); + + unsafe { + lut.set_len(256); + ilut.set_len(256); + txt.set_len(CT_LEN); + enc.set_len(CT_LEN); + dec.set_len(CT_LEN); + } + + generate_lut(&mut lut); + generate_ilut(&lut, &mut ilut); + + let mut rng = thread_rng(); + + rng.fill_bytes(&mut txt); + enc.fill(0u8); + dec.fill(0u8); + + par_encrypt_data(&lut, &txt, &mut enc); + par_decrypt_data(&ilut, &enc, &mut dec); + + let flag = AtomicBool::new(false); + + (0..CT_LEN).into_par_iter().for_each(|i| { + flag.fetch_or((txt[i] ^ dec[i]) != 0, Ordering::Relaxed); + }); + + assert_eq!(flag.load(Ordering::SeqCst), false); + } } diff --git a/wrapper/rust/src/lib.rs b/wrapper/rust/src/lib.rs index 4e9fd31..a81a4fd 100644 --- a/wrapper/rust/src/lib.rs +++ b/wrapper/rust/src/lib.rs @@ -1,2 +1,4 @@ +extern crate rayon; extern crate static_assertions; + pub mod harpocrates; From 5714599993eff8c965b77b204d2cac0b0f6b0752 Mon Sep 17 00:00:00 2001 From: Anjan Roy Date: Mon, 16 May 2022 13:00:09 +0530 Subject: [PATCH 10/11] benchmark large byte chunk encryption/ decryption routines, using Harpocrates cipher [including multi-threaded variant] Signed-off-by: Anjan Roy --- wrapper/rust/benches/harpocrates.rs | 133 ++++++++++++++++++++++++++-- 1 file changed, 127 insertions(+), 6 deletions(-) diff --git a/wrapper/rust/benches/harpocrates.rs b/wrapper/rust/benches/harpocrates.rs index ede45bb..141d235 100644 --- a/wrapper/rust/benches/harpocrates.rs +++ b/wrapper/rust/benches/harpocrates.rs @@ -1,10 +1,13 @@ extern crate criterion; -use criterion::{black_box, criterion_group, criterion_main, Criterion}; -use harpocrates::harpocrates::{decrypt, encrypt, generate_ilut, generate_lut}; +use criterion::{black_box, criterion_group, criterion_main, Criterion, Throughput}; +use harpocrates::harpocrates::{ + decrypt, decrypt_data, encrypt, encrypt_data, generate_ilut, generate_lut, par_decrypt_data, + par_encrypt_data, +}; use rand::prelude::*; -fn bench_harpocrates(c: &mut Criterion) { +fn bench_harpocrates_basic(c: &mut Criterion) { let mut lut = [0u8; 256]; let mut ilut = [0u8; 256]; @@ -27,18 +30,136 @@ fn bench_harpocrates(c: &mut Criterion) { enc.fill(0u8); dec.fill(0u8); - c.bench_function("harpocrates_encrypt", |b| { + let mut grp = c.benchmark_group("harpocrates"); + grp.throughput(Throughput::Bytes(16)); + + grp.bench_function("encrypt", |b| { b.iter(|| { encrypt(black_box(&lut), black_box(&txt), black_box(&mut enc)); }); }); - c.bench_function("harpocrates_decrypt", |b| { + grp.bench_function("decrypt", |b| { b.iter(|| { decrypt(black_box(&ilut), black_box(&enc), black_box(&mut dec)); }); }); + + grp.finish(); +} + +fn to_readable_data_size(b_len: usize) -> String { + const GB: f64 = 1073741824.; // 1 << 30 bytes + const MB: f64 = 1048576.; // 1 << 20 bytes + const KB: f64 = 1024.; // 1 << 10 bytes + + let b_len_ = b_len as f64; + + if b_len_ >= GB { + format!("{} GB", b_len_ / GB) + } else if b_len_ >= MB { + format!("{} MB", b_len_ / MB) + } else if b_len_ >= KB { + format!("{} KB", b_len_ / KB) + } else { + format!("{} B", b_len_) + } +} + +fn bench_harpocrates_with_data_chunks(c: &mut Criterion) { + let mut lut = [0u8; 256]; + let mut ilut = [0u8; 256]; + + generate_lut(&mut lut); + generate_ilut(&lut, &mut ilut); + + let mut rng = thread_rng(); + let mut grp = c.benchmark_group("harpocrates_with_data_chunks"); + grp.sample_size(10); + + const CT_LEN: [usize; 3] = [1 << 24, 1 << 25, 1 << 26]; + + for ct_len in CT_LEN { + let mut txt = Vec::::with_capacity(ct_len); + let mut enc = Vec::::with_capacity(ct_len); + let mut dec = Vec::::with_capacity(ct_len); + + unsafe { + txt.set_len(ct_len); + enc.set_len(ct_len); + dec.set_len(ct_len); + } + + rng.fill_bytes(&mut txt); + enc.fill(0u8); + dec.fill(0u8); + + grp.throughput(Throughput::Bytes(ct_len as u64)); + + grp.bench_function(format!("encrypt/{}", to_readable_data_size(ct_len)), |b| { + b.iter(|| { + encrypt_data(black_box(&lut), black_box(&txt), black_box(&mut enc)); + }); + }); + grp.bench_function(format!("decrypt/{}", to_readable_data_size(ct_len)), |b| { + b.iter(|| { + decrypt_data(black_box(&ilut), black_box(&enc), black_box(&mut dec)); + }); + }); + } + + grp.finish(); +} + +fn bench_par_harpocrates_with_data_chunks(c: &mut Criterion) { + let mut lut = [0u8; 256]; + let mut ilut = [0u8; 256]; + + generate_lut(&mut lut); + generate_ilut(&lut, &mut ilut); + + let mut rng = thread_rng(); + let mut grp = c.benchmark_group("par_harpocrates_with_data_chunks"); + grp.sample_size(10); + + const CT_LEN: [usize; 3] = [1 << 24, 1 << 25, 1 << 26]; + + for ct_len in CT_LEN { + let mut txt = Vec::::with_capacity(ct_len); + let mut enc = Vec::::with_capacity(ct_len); + let mut dec = Vec::::with_capacity(ct_len); + + unsafe { + txt.set_len(ct_len); + enc.set_len(ct_len); + dec.set_len(ct_len); + } + + rng.fill_bytes(&mut txt); + enc.fill(0u8); + dec.fill(0u8); + + grp.throughput(Throughput::Bytes(ct_len as u64)); + + grp.bench_function(format!("encrypt/{}", to_readable_data_size(ct_len)), |b| { + b.iter(|| { + par_encrypt_data(black_box(&lut), black_box(&txt), black_box(&mut enc)); + }); + }); + grp.bench_function(format!("decrypt/{}", to_readable_data_size(ct_len)), |b| { + b.iter(|| { + par_decrypt_data(black_box(&ilut), black_box(&enc), black_box(&mut dec)); + }); + }); + } + + grp.finish(); } -criterion_group!(harpocrates, bench_harpocrates); +criterion_group!( + harpocrates, + bench_harpocrates_basic, + bench_harpocrates_with_data_chunks, + bench_par_harpocrates_with_data_chunks +); criterion_main!(harpocrates); From 9966e70d8acc07fbd1334410288e7a8d6376e05c Mon Sep 17 00:00:00 2001 From: Anjan Roy Date: Mon, 16 May 2022 14:10:27 +0530 Subject: [PATCH 11/11] benchmark results of rust wrapper api, on ARM Cortex-A72 Signed-off-by: Anjan Roy --- results/cpu/rust_api.md | 199 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 results/cpu/rust_api.md diff --git a/results/cpu/rust_api.md b/results/cpu/rust_api.md new file mode 100644 index 0000000..412f5f8 --- /dev/null +++ b/results/cpu/rust_api.md @@ -0,0 +1,199 @@ +# Benchmarking Rust API of Harpocrates Cipher on ARM Cortex-A72 + +Compile, link & execute benchmark using cargo-criterion + +```bash +# assuming you've already installed cargo-criterion, if not +# +# cargo install cargo-criterion + +make bench_rust +``` + +```bash +$ lscpu | grep -i cpu\(s\) # available number of CPU cores + +CPU(s): 16 +On-line CPU(s) list: 0-15 +NUMA node0 CPU(s): 0-15 +``` + +## Basic Harpocrates Encrypt/ Decrypt Rust API + +```bash +harpocrates/encrypt time: [1.8458 us 1.8458 us 1.8459 us] + thrpt: [8.2664 MiB/s 8.2667 MiB/s 8.2670 MiB/s] + change: + time: [-0.0120% +0.0009% +0.0166%] (p = 0.92 > 0.05) + thrpt: [-0.0165% -0.0009% +0.0120%] + No change in performance detected. +Found 8 outliers among 100 measurements (8.00%) + 1 (1.00%) low severe + 1 (1.00%) low mild + 3 (3.00%) high mild + 3 (3.00%) high severe +slope [1.8458 us 1.8459 us] R^2 [0.9999967 0.9999966] +mean [1.8458 us 1.8462 us] std. dev. [243.42 ps 2.2510 ns] +median [1.8457 us 1.8458 us] med. abs. dev. [92.281 ps 208.90 ps] + +harpocrates/decrypt time: [1.8294 us 1.8295 us 1.8296 us] + thrpt: [8.3402 MiB/s 8.3406 MiB/s 8.3410 MiB/s] + change: + time: [-0.1231% -0.0339% +0.0164%] (p = 0.62 > 0.05) + thrpt: [-0.0163% +0.0340% +0.1232%] + No change in performance detected. +Found 15 outliers among 100 measurements (15.00%) + 1 (1.00%) low severe + 9 (9.00%) high mild + 5 (5.00%) high severe +slope [1.8294 us 1.8296 us] R^2 [0.9999939 0.9999938] +mean [1.8294 us 1.8297 us] std. dev. [432.77 ps 985.24 ps] +median [1.8293 us 1.8294 us] med. abs. dev. [137.70 ps 281.54 ps] +``` + +## Sequential Harpocrates Rust API for Encrypting/ Decrypting Large Byte Arrays + +Benchmarks routine which encrypts/ decrypts N -many byte chunks sequentially ( one after another ) | total input/ output size = (N << 4) -bytes ∈ {16MB, 32MB, 64MB} + +```bash +harpocrates_with_data_chunks/encrypt/16 MB + time: [1.9323 s 1.9323 s 1.9324 s] + thrpt: [8.2799 MiB/s 8.2801 MiB/s 8.2802 MiB/s] + change: + time: [+0.0050% +0.0070% +0.0090%] (p = 0.00 < 0.05) + thrpt: [-0.0090% -0.0070% -0.0050%] + Change within noise threshold. +mean [1.9323 s 1.9324 s] std. dev. [28.010 us 69.871 us] +median [1.9323 s 1.9324 s] med. abs. dev. [2.3410 us 108.39 us] + +harpocrates_with_data_chunks/decrypt/16 MB + time: [1.9125 s 1.9126 s 1.9127 s] + thrpt: [8.3653 MiB/s 8.3657 MiB/s 8.3661 MiB/s] + change: + time: [+0.0036% +0.0083% +0.0134%] (p = 0.01 < 0.05) + thrpt: [-0.0134% -0.0083% -0.0036%] + Change within noise threshold. +mean [1.9125 s 1.9127 s] std. dev. [93.212 us 187.07 us] +median [1.9124 s 1.9127 s] med. abs. dev. [10.111 us 250.81 us] + +harpocrates_with_data_chunks/encrypt/32 MB + time: [3.8643 s 3.8644 s 3.8644 s] + thrpt: [8.2807 MiB/s 8.2808 MiB/s 8.2809 MiB/s] + change: + time: [-0.0056% -0.0036% -0.0019%] (p = 0.00 < 0.05) + thrpt: [+0.0019% +0.0036% +0.0056%] + Change within noise threshold. +Found 2 outliers among 10 measurements (20.00%) + 2 (20.00%) low mild +mean [3.8643 s 3.8644 s] std. dev. [32.688 us 111.53 us] +median [3.8643 s 3.8644 s] med. abs. dev. [4.8733 us 147.82 us] + +harpocrates_with_data_chunks/decrypt/32 MB + time: [3.8250 s 3.8250 s 3.8250 s] + thrpt: [8.3659 MiB/s 8.3660 MiB/s 8.3661 MiB/s] + change: + time: [-0.0004% +0.0006% +0.0019%] (p = 0.34 > 0.05) + thrpt: [-0.0019% -0.0006% +0.0004%] + No change in performance detected. +Found 1 outliers among 10 measurements (10.00%) + 1 (10.00%) high mild +mean [3.8250 s 3.8250 s] std. dev. [34.369 us 92.670 us] +median [3.8249 s 3.8250 s] med. abs. dev. [6.6658 us 119.06 us] + +harpocrates_with_data_chunks/encrypt/64 MB + time: [7.7289 s 7.7294 s 7.7304 s] + thrpt: [8.2790 MiB/s 8.2801 MiB/s 8.2806 MiB/s] + change: + time: [-0.0025% +0.0048% +0.0181%] (p = 0.66 > 0.05) + thrpt: [-0.0181% -0.0048% +0.0025%] + No change in performance detected. +Found 2 outliers among 10 measurements (20.00%) + 1 (10.00%) high mild + 1 (10.00%) high severe +mean [7.7289 s 7.7304 s] std. dev. [45.321 us 2.4537 ms] +median [7.7289 s 7.7290 s] med. abs. dev. [24.053 us 207.60 us] + +harpocrates_with_data_chunks/decrypt/64 MB + time: [7.6499 s 7.6499 s 7.6500 s] + thrpt: [8.3660 MiB/s 8.3661 MiB/s 8.3661 MiB/s] + change: + time: [-0.0052% -0.0041% -0.0031%] (p = 0.00 < 0.05) + thrpt: [+0.0031% +0.0041% +0.0052%] + Change within noise threshold. +mean [7.6499 s 7.6500 s] std. dev. [50.185 us 104.79 us] +median [7.6499 s 7.6500 s] med. abs. dev. [7.4293 us 147.40 us] +``` + +## Parallel Harpocrates Rust API for Encrypting/ Decrypting Large Byte Arrays + +Benchmarks routine which parallelly encrypts/ decrypts N -many byte chunks ( spreading computation over all available CPU cores ) | total input/ output size = (N << 4) -bytes ∈ {16MB, 32MB, 64MB} + +```bash +par_harpocrates_with_data_chunks/encrypt/16 MB + time: [122.05 ms 122.53 ms 122.86 ms] + thrpt: [130.23 MiB/s 130.58 MiB/s 131.09 MiB/s] + change: + time: [-0.6625% -0.1642% +0.3855%] (p = 0.56 > 0.05) + thrpt: [-0.3841% +0.1645% +0.6669%] + No change in performance detected. +slope [122.05 ms 122.86 ms] R^2 [0.9993045 0.9994527] +mean [121.73 ms 122.70 ms] std. dev. [471.65 us 1.0510 ms] +median [121.33 ms 122.79 ms] med. abs. dev. [117.37 us 1.3988 ms] + +par_harpocrates_with_data_chunks/decrypt/16 MB + time: [120.74 ms 121.10 ms 121.70 ms] + thrpt: [131.47 MiB/s 132.12 MiB/s 132.51 MiB/s] + change: + time: [-1.0900% -0.1300% +0.7273%] (p = 0.80 > 0.05) + thrpt: [-0.7220% +0.1302% +1.1020%] + No change in performance detected. +Found 1 outliers among 10 measurements (10.00%) + 1 (10.00%) high mild +slope [120.74 ms 121.70 ms] R^2 [0.9992336 0.9989205] +mean [120.74 ms 122.04 ms] std. dev. [368.45 us 1.4857 ms] +median [120.65 ms 122.02 ms] med. abs. dev. [128.34 us 1.6619 ms] + +par_harpocrates_with_data_chunks/encrypt/32 MB + time: [243.74 ms 244.68 ms 246.11 ms] + thrpt: [130.02 MiB/s 130.79 MiB/s 131.29 MiB/s] + change: + time: [-0.3333% +0.2045% +0.8007%] (p = 0.58 > 0.05) + thrpt: [-0.7943% -0.2041% +0.3344%] + No change in performance detected. +Found 1 outliers among 10 measurements (10.00%) + 1 (10.00%) high severe +mean [243.74 ms 246.11 ms] std. dev. [495.12 us 3.2186 ms] +median [243.45 ms 244.82 ms] med. abs. dev. [191.67 us 1.7622 ms] + +par_harpocrates_with_data_chunks/decrypt/32 MB + time: [241.04 ms 241.43 ms 241.89 ms] + thrpt: [132.29 MiB/s 132.54 MiB/s 132.76 MiB/s] + change: + time: [-0.3068% -0.0047% +0.3188%] (p = 0.98 > 0.05) + thrpt: [-0.3178% +0.0047% +0.3078%] + No change in performance detected. +Found 1 outliers among 10 measurements (10.00%) + 1 (10.00%) high mild +mean [241.04 ms 241.89 ms] std. dev. [327.64 us 999.79 us] +median [240.82 ms 241.86 ms] med. abs. dev. [135.53 us 1.1338 ms] + +par_harpocrates_with_data_chunks/encrypt/64 MB + time: [486.95 ms 487.42 ms 487.92 ms] + thrpt: [131.17 MiB/s 131.30 MiB/s 131.43 MiB/s] + change: + time: [-0.1703% -0.0079% +0.1559%] (p = 0.92 > 0.05) + thrpt: [-0.1557% +0.0079% +0.1706%] + No change in performance detected. +mean [486.95 ms 487.92 ms] std. dev. [448.71 us 1.0093 ms] +median [486.65 ms 488.06 ms] med. abs. dev. [105.41 us 1.4396 ms] + +par_harpocrates_with_data_chunks/decrypt/64 MB + time: [481.38 ms 481.88 ms 482.36 ms] + thrpt: [132.68 MiB/s 132.81 MiB/s 132.95 MiB/s] + change: + time: [-0.1653% -0.0188% +0.1279%] (p = 0.81 > 0.05) + thrpt: [-0.1278% +0.0188% +0.1656%] + No change in performance detected. +mean [481.38 ms 482.36 ms] std. dev. [486.98 us 1.0680 ms] +median [481.18 ms 482.49 ms] med. abs. dev. [14.421 us 1.3692 ms] +```