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/Makefile b/Makefile index b8a7d5f..80c98ee 100644 --- a/Makefile +++ b/Makefile @@ -19,6 +19,15 @@ 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 + +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 $@ 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] +``` diff --git a/wrapper/harpocrates.cpp b/wrapper/harpocrates.cpp new file mode 100644 index 0000000..9292392 --- /dev/null +++ b/wrapper/harpocrates.cpp @@ -0,0 +1,86 @@ +#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 generate_harpocrates_lut(uint8_t* const); + + void generate_harpocrates_ilut(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 harpocrates_decrypt(const uint8_t* const __restrict, + const uint8_t* const __restrict, + uint8_t* const __restrict); +} + +// 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_harpocrates_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_harpocrates_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 + // + // 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 harpocrates_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 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..8aa6ad5 --- /dev/null +++ b/wrapper/rust/Cargo.lock @@ -0,0 +1,667 @@ +# This file is automatically @generated by Cargo. +# 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", + "rayon", + "static_assertions", +] + +[[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 = "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" +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 new file mode 100644 index 0000000..482b6ae --- /dev/null +++ b/wrapper/rust/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "harpocrates" +version = "0.1.0" +edition = "2021" + +[dependencies] +static_assertions = "1.1.0" +rayon = "1.5.3" + +[dev-dependencies] +rand = "0.8.4" +criterion = "0.3.5" + +[[bench]] +name = "harpocrates" +harness = false diff --git a/wrapper/rust/benches/harpocrates.rs b/wrapper/rust/benches/harpocrates.rs new file mode 100644 index 0000000..141d235 --- /dev/null +++ b/wrapper/rust/benches/harpocrates.rs @@ -0,0 +1,165 @@ +extern crate criterion; + +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_basic(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); + + 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)); + }); + }); + + 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_basic, + bench_harpocrates_with_data_chunks, + bench_par_harpocrates_with_data_chunks +); +criterion_main!(harpocrates); 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..f763763 --- /dev/null +++ b/wrapper/rust/src/harpocrates.rs @@ -0,0 +1,267 @@ +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()); + } +} + +/// 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]); + } +} + +/// 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() { + 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]); + } + } + + #[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]); + } + } + + #[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 new file mode 100644 index 0000000..a81a4fd --- /dev/null +++ b/wrapper/rust/src/lib.rs @@ -0,0 +1,4 @@ +extern crate rayon; +extern crate static_assertions; + +pub mod harpocrates;