|
1 | 1 | # xoodyak
|
2 | 2 | Accelerated Xoodyak - A Lightweight Cryptographic Scheme
|
| 3 | + |
| 4 | +## Overview |
| 5 | + |
| 6 | +After implementing `ascon` & `tinyjambu` -- two finalists of NIST **L**ight **W**eight **C**ryptography competition, I've picked up `xoodyak`, which is another finalist of NIST LWC call. Xoodyak cryptograhic suite, as submitted in NIST LWC call, offers following two features |
| 7 | + |
| 8 | +- **[Xoodyak Hash]** Computes cryptographically secure hash of input message M, of lenth N (>=0) |
| 9 | +- **[Xoodyak AEAD]** Given 16 -bytes secret key, 16 -bytes public message nonce, N (>=0) -bytes associated data & M (>=0) -bytes plain text data, one party computes M -bytes encrypted text, along with 16 -bytes authentication tag. Now other side of communication can perform verified decryption of encrypted plain text, when it has access to following pieces of information |
| 10 | + - 16 -bytes secret key |
| 11 | + - 16 -bytes nonce |
| 12 | + - 16 -bytes authentication tag |
| 13 | + - N -bytes associated data |
| 14 | + - M -bytes encrypted text |
| 15 | + |
| 16 | +Receiving party can verify authenticity & integrity of encrypted message by asserting truth value in boolean flag returned from `decrypt(...)` routine. If verification flag is not truth value, decrypted text should never be consumed. |
| 17 | + |
| 18 | +> Note, associated data is never encrypted |
| 19 | +
|
| 20 | +> AEAD -> Authenticated Encryption with Associated Data |
| 21 | +
|
| 22 | +In this repository, I'm keeping a simple, zero-dependency, easy-to-use header-only C++ library ( using C++20 features ), which implements Xoodyak specification. Along with that I also maintain Python wrapper API, which under the hood makes use of C-ABI conformant shared library object. |
| 23 | + |
| 24 | +> To learn more about AEAD, see [here](https://en.wikipedia.org/wiki/Authenticated_encryption) |
| 25 | +
|
| 26 | +> If interested in my work on `ascon`, see [here](https://github.com/itzmeanjan/ascon) |
| 27 | +
|
| 28 | +> If interested in my work on `tinyjambu`, see [here](https://github.com/itzmeanjan/tinyjambu) |
| 29 | +
|
| 30 | +> Xoodyak specification, which I followed during this implementation, lives [here](https://csrc.nist.gov/CSRC/media/Projects/lightweight-cryptography/documents/finalist-round/updated-spec-doc/xoodyak-spec-final.pdf) |
| 31 | +
|
| 32 | +## Prerequisites |
| 33 | + |
| 34 | +- Ensure you've C++ compiler such as `dpcpp`/ `clang++`/ `g++`, with C++20 standard library specification implemented |
| 35 | + |
| 36 | +> I'm using |
| 37 | +
|
| 38 | +```bash |
| 39 | +$dpcpp --version |
| 40 | + |
| 41 | +Intel(R) oneAPI DPC++/C++ Compiler 2022.0.0 (2022.0.0.20211123) |
| 42 | +Target: x86_64-unknown-linux-gnu |
| 43 | +Thread model: posix |
| 44 | +InstalledDir: /opt/intel/oneapi/compiler/2022.0.2/linux/bin-llvm |
| 45 | +``` |
| 46 | + |
| 47 | +```bash |
| 48 | +$ g++ --version |
| 49 | + |
| 50 | +g++ (Ubuntu 11.2.0-19ubuntu1) 11.2.0 |
| 51 | +``` |
| 52 | + |
| 53 | +- You should also have standard system development utilities such as `make`, `cmake` |
| 54 | + |
| 55 | +> I'm using |
| 56 | +
|
| 57 | +```bash |
| 58 | +$ make -v |
| 59 | + |
| 60 | +GNU Make 4.2.1 |
| 61 | +``` |
| 62 | + |
| 63 | +```bash |
| 64 | +$ cmake --version |
| 65 | + |
| 66 | +cmake version 3.16.3 |
| 67 | +``` |
| 68 | + |
| 69 | +- For benchmarking Xoodyak implementation on CPU, you'll need to have `google-benchmark` installed; follow [this](https://github.com/google/benchmark/tree/60b16f1#installation) |
| 70 | + |
| 71 | +- For using/ testing Python wrapper API of Xoodyak, you need to have `python3`, along with dependencies which can be easily installed using `pip` |
| 72 | + |
| 73 | +> I'm using |
| 74 | +
|
| 75 | +```bash |
| 76 | +$ python3 --version |
| 77 | + |
| 78 | +Python 3.10.4 |
| 79 | +``` |
| 80 | + |
| 81 | +> Install Python dependencies |
| 82 | +
|
| 83 | +```bash |
| 84 | +pushd wrapper/python |
| 85 | +python3 -m pip install -r requirements.txt # ensure you've pip installed |
| 86 | +popd |
| 87 | +``` |
| 88 | + |
| 89 | +> It's better idea to isolate Xoodyak Python API dependency installation from system Python installation, using `virtualenv` |
| 90 | +
|
| 91 | +```bash |
| 92 | +# install virtualenv itself |
| 93 | +python3 -m pip install --user virtualenv |
| 94 | + |
| 95 | +pushd wrapper/python |
| 96 | +# create virtualenv enabled workspace |
| 97 | +python3 -m virtualenv . |
| 98 | + |
| 99 | +# activate virtual environment |
| 100 | +source bin/activate |
| 101 | +# install all dependencies inside virtual environment |
| 102 | +python3 -m pip install -r requirements.txt |
| 103 | + |
| 104 | +# work inside virtual environment |
| 105 | +# when done, issue following command |
| 106 | +# ... |
| 107 | + |
| 108 | +deactivate |
| 109 | +popd |
| 110 | +``` |
| 111 | + |
| 112 | +## Testing |
| 113 | + |
| 114 | +For testing functional correctness of Xoodyak cryptographic suite implementation, I've written following tests |
| 115 | + |
| 116 | +- Given 16 -bytes random secret key, 16 -bytes random public message nonce, N (>=0) -bytes random associated data & M (>=0) -bytes random plain text |
| 117 | + - Ensure, in ideal condition, everything works as expected, while executing encrypt -> decrypt -> byte-by-byte comparison of plain & decrypted text |
| 118 | + - Same as above point, just that before attempting decryption, to check that claimed security properties are working as expected in this implementation, mutation of secret key/ nonce/ tag/ encrypted data/ associated data ( even a single bit flip is sufficient ) is performed, while asserting that verified decryption attempt must fail ( read boolean verification flag must not be truth value ). |
| 119 | +- Given Known Answer Tests as submitted with Xoodyak package in NIST LWC call, this implementation computed results are asserted against KATs, to ensure correctness & conformance to specified standard. Both Xoodyak Hash & AEAD are checked. |
| 120 | + |
| 121 | +For executing first kind of test, issue |
| 122 | + |
| 123 | +```bash |
| 124 | +make # uses C++ API of Xoodyak |
| 125 | +``` |
| 126 | + |
| 127 | +And if interested in testing against KAT, issue |
| 128 | + |
| 129 | +```bash |
| 130 | +make test_kat # uses Python API of Xoodyak |
| 131 | +``` |
| 132 | + |
| 133 | +## Benchmarking |
| 134 | + |
| 135 | +For benchmarking following implementations of Xoodyak cryptographic suite, on CPU |
| 136 | + |
| 137 | +- Xoodyak cryptographic hash function |
| 138 | +- Xoodyak Authenticated Encryption |
| 139 | +- Xoodyak Verified Decryption |
| 140 | + |
| 141 | +issue |
| 142 | + |
| 143 | +```bash |
| 144 | +make benchmark # must have `google-benchmark` |
| 145 | +``` |
| 146 | + |
| 147 | +### On ARM Cortex A72 |
| 148 | + |
| 149 | +```bash |
| 150 | +2022-05-01T12:56:18+05:30 |
| 151 | +Running ./bench/a.out |
| 152 | +Run on (4 X 1800 MHz CPU s) |
| 153 | +Load Average: 2.08, 1.62, 1.22 |
| 154 | +---------------------------------------------------------------------------- |
| 155 | +Benchmark Time CPU Iterations UserCounters... |
| 156 | +---------------------------------------------------------------------------- |
| 157 | +hash_32B 1624 ns 1623 ns 430893 bytes_per_second=18.8083M/s items_per_second=616.312k/s |
| 158 | +hash_64B 2703 ns 2701 ns 259709 bytes_per_second=22.5967M/s items_per_second=370.224k/s |
| 159 | +hash_128B 4856 ns 4853 ns 144248 bytes_per_second=25.1521M/s items_per_second=206.046k/s |
| 160 | +hash_256B 9140 ns 9134 ns 76253 bytes_per_second=26.7274M/s items_per_second=109.475k/s |
| 161 | +hash_512B 17692 ns 17681 ns 39536 bytes_per_second=27.6156M/s items_per_second=56.5568k/s |
| 162 | +hash_1024B 34827 ns 34804 ns 20104 bytes_per_second=28.059M/s items_per_second=28.7324k/s |
| 163 | +hash_2048B 69142 ns 69084 ns 10074 bytes_per_second=28.2716M/s items_per_second=14.4751k/s |
| 164 | +hash_4096B 138000 ns 137904 ns 5071 bytes_per_second=28.3258M/s items_per_second=7.25141k/s |
| 165 | +encrypt_32B_64B 2842 ns 2840 ns 246751 bytes_per_second=32.2397M/s items_per_second=352.143k/s |
| 166 | +encrypt_32B_128B 4561 ns 4560 ns 153488 bytes_per_second=33.4641M/s items_per_second=219.31k/s |
| 167 | +encrypt_32B_256B 7508 ns 7493 ns 93049 bytes_per_second=36.6568M/s items_per_second=133.463k/s |
| 168 | +encrypt_32B_512B 13929 ns 13919 ns 50197 bytes_per_second=37.2723M/s items_per_second=71.8435k/s |
| 169 | +encrypt_32B_1024B 26020 ns 26004 ns 26613 bytes_per_second=38.728M/s items_per_second=38.4557k/s |
| 170 | +encrypt_32B_2048B 51320 ns 51246 ns 13565 bytes_per_second=38.7081M/s items_per_second=19.5136k/s |
| 171 | +encrypt_32B_4096B 100408 ns 100278 ns 6960 bytes_per_second=39.2587M/s items_per_second=9.97232k/s |
| 172 | +decrypt_32B_64B 2833 ns 2832 ns 246742 bytes_per_second=32.3304M/s items_per_second=353.134k/s |
| 173 | +decrypt_32B_128B 4600 ns 4597 ns 152423 bytes_per_second=33.1935M/s items_per_second=217.537k/s |
| 174 | +decrypt_32B_256B 7655 ns 7650 ns 91801 bytes_per_second=35.9025M/s items_per_second=130.717k/s |
| 175 | +decrypt_32B_512B 13929 ns 13924 ns 50078 bytes_per_second=37.2584M/s items_per_second=71.8166k/s |
| 176 | +decrypt_32B_1024B 26934 ns 26913 ns 25977 bytes_per_second=37.4197M/s items_per_second=37.1566k/s |
| 177 | +decrypt_32B_2048B 51258 ns 51226 ns 13536 bytes_per_second=38.7235M/s items_per_second=19.5214k/s |
| 178 | +decrypt_32B_4096B 102996 ns 102940 ns 6851 bytes_per_second=38.2432M/s items_per_second=9.71437k/s |
| 179 | +``` |
| 180 | + |
| 181 | +### On Intel(R) Xeon(R) CPU E5-2686 v4 @ 2.30GHz |
| 182 | + |
| 183 | +```bash |
| 184 | +2022-05-01T07:34:18+00:00 |
| 185 | +Running ./bench/a.out |
| 186 | +Run on (4 X 2300.07 MHz CPU s) |
| 187 | +CPU Caches: |
| 188 | + L1 Data 32 KiB (x2) |
| 189 | + L1 Instruction 32 KiB (x2) |
| 190 | + L2 Unified 256 KiB (x2) |
| 191 | + L3 Unified 46080 KiB (x1) |
| 192 | +Load Average: 0.08, 0.02, 0.01 |
| 193 | +---------------------------------------------------------------------------- |
| 194 | +Benchmark Time CPU Iterations UserCounters... |
| 195 | +---------------------------------------------------------------------------- |
| 196 | +hash_32B 465 ns 465 ns 1506912 bytes_per_second=65.6857M/s items_per_second=2.15239M/s |
| 197 | +hash_64B 776 ns 776 ns 900928 bytes_per_second=78.64M/s items_per_second=1.28844M/s |
| 198 | +hash_128B 1396 ns 1396 ns 501084 bytes_per_second=87.4257M/s items_per_second=716.191k/s |
| 199 | +hash_256B 2634 ns 2634 ns 265735 bytes_per_second=92.6943M/s items_per_second=379.676k/s |
| 200 | +hash_512B 5117 ns 5117 ns 136725 bytes_per_second=95.4322M/s items_per_second=195.445k/s |
| 201 | +hash_1024B 10079 ns 10078 ns 69482 bytes_per_second=96.8969M/s items_per_second=99.2224k/s |
| 202 | +hash_2048B 19989 ns 19989 ns 34888 bytes_per_second=97.7103M/s items_per_second=50.0277k/s |
| 203 | +hash_4096B 39820 ns 39817 ns 17573 bytes_per_second=98.1049M/s items_per_second=25.1149k/s |
| 204 | +encrypt_32B_64B 839 ns 839 ns 834154 bytes_per_second=109.108M/s items_per_second=1.19175M/s |
| 205 | +encrypt_32B_128B 1348 ns 1348 ns 523189 bytes_per_second=113.16M/s items_per_second=741.605k/s |
| 206 | +encrypt_32B_256B 2186 ns 2186 ns 320184 bytes_per_second=125.673M/s items_per_second=457.561k/s |
| 207 | +encrypt_32B_512B 4048 ns 4048 ns 172988 bytes_per_second=128.152M/s items_per_second=247.018k/s |
| 208 | +encrypt_32B_1024B 7613 ns 7613 ns 92006 bytes_per_second=132.291M/s items_per_second=131.361k/s |
| 209 | +encrypt_32B_2048B 14880 ns 14879 ns 47040 bytes_per_second=133.314M/s items_per_second=67.2068k/s |
| 210 | +encrypt_32B_4096B 30435 ns 30434 ns 23025 bytes_per_second=129.353M/s items_per_second=32.8577k/s |
| 211 | +decrypt_32B_64B 874 ns 874 ns 801116 bytes_per_second=104.729M/s items_per_second=1.14392M/s |
| 212 | +decrypt_32B_128B 1377 ns 1377 ns 504551 bytes_per_second=110.805M/s items_per_second=726.172k/s |
| 213 | +decrypt_32B_256B 2249 ns 2249 ns 311649 bytes_per_second=122.129M/s items_per_second=444.657k/s |
| 214 | +decrypt_32B_512B 4107 ns 4107 ns 170027 bytes_per_second=126.314M/s items_per_second=243.475k/s |
| 215 | +decrypt_32B_1024B 7785 ns 7785 ns 89754 bytes_per_second=129.364M/s items_per_second=128.455k/s |
| 216 | +decrypt_32B_2048B 15248 ns 15247 ns 45901 bytes_per_second=130.099M/s items_per_second=65.5857k/s |
| 217 | +decrypt_32B_4096B 30294 ns 30293 ns 23118 bytes_per_second=129.957M/s items_per_second=33.0111k/s |
| 218 | +``` |
| 219 | + |
| 220 | +## Usage |
| 221 | + |
| 222 | +Xoodyak being a header-only C++ library, using it is as easy as including [`xoodyak.hpp`](https://github.com/itzmeanjan/xoodyak/blob/f366012/include/xoodyak.hpp) in your C++ program & adding `./include` to your include path. I've written two examples demonstrating usage of Xoodyak C++ API |
| 223 | + |
| 224 | +- Xoodyak Hash; see [here](https://github.com/itzmeanjan/xoodyak/blob/f366012/example/xoodyak_hash.cpp) |
| 225 | +- Xoodyak AEAD; see [here](https://github.com/itzmeanjan/xoodyak/blob/f366012/example/xoodyak_aead.cpp) |
0 commit comments