{"id":15833767,"url":"https://github.com/itzmeanjan/sha3","last_synced_at":"2025-03-15T08:31:50.741Z","repository":{"id":106438538,"uuid":"535987847","full_name":"itzmeanjan/sha3","owner":"itzmeanjan","description":"Compile-time Evaluable SHA3: Permutation-Based Hash and Extendable-Output Functions","archived":false,"fork":false,"pushed_at":"2024-01-20T12:45:34.000Z","size":4878,"stargazers_count":12,"open_issues_count":0,"forks_count":1,"subscribers_count":5,"default_branch":"master","last_synced_at":"2024-10-06T13:42:05.855Z","etag":null,"topics":["constexpr","constexpr-all-the-things","extendable-output-functions","hash-functions","incremental-hashing","keccak","keccak-sponge","permutation","sha3","sha3-224","sha3-256","sha3-384","sha3-512","shake128","shake256","xof"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"cc0-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/itzmeanjan.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-09-13T06:25:37.000Z","updated_at":"2024-07-16T02:26:18.000Z","dependencies_parsed_at":"2023-04-23T11:17:10.384Z","dependency_job_id":"9854c16d-1251-4040-bbbf-fa44d2568cf3","html_url":"https://github.com/itzmeanjan/sha3","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/itzmeanjan%2Fsha3","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/itzmeanjan%2Fsha3/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/itzmeanjan%2Fsha3/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/itzmeanjan%2Fsha3/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/itzmeanjan","download_url":"https://codeload.github.com/itzmeanjan/sha3/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243707282,"owners_count":20334613,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["constexpr","constexpr-all-the-things","extendable-output-functions","hash-functions","incremental-hashing","keccak","keccak-sponge","permutation","sha3","sha3-224","sha3-256","sha3-384","sha3-512","shake128","shake256","xof"],"created_at":"2024-10-05T13:42:11.504Z","updated_at":"2025-03-15T08:31:50.733Z","avatar_url":"https://github.com/itzmeanjan.png","language":"C++","readme":"# sha3\n`constexpr` ( i.e. **Compile-time Evaluable** ) SHA3: Permutation-Based Hash and Extendable-Output Functions.\n\n## Overview\n\nSHA3 standard by NIST ( i.e. NIST FIPS PUB 202 ) specifies four ( of different digest length ) permutation-based hash functions and two extendable-output functions, which are built on top of keccak-p[1600, 24] permutation.\n\nThese hash functions and extendable output functions are pretty commonly used in various post-quantum cryptography algorithms ( those used for public key encryption, key establishment mechanism \u0026 digital signature ), some of which are already declared as selected candidates ( e.g. Kyber, Falcon, Dilithium, SPHINCS+ etc. ) of NIST PQC standardization effort - waiting to be standardized or some are still competing. I decided to implement SHA3 specification as a **header-only C++ library**, so that I can make use of it as a modular dependency ( say pinned to specific commit using git submodule ) in libraries where I implement various PQC schemes.\n\nFew of those places, where I've already used `sha3` as ( git submodule based ) dependency\n\n- [Kyber: Post-Quantum Public-key Encryption \u0026 Key-establishment Algorithm](https://github.com/itzmeanjan/kyber)\n- [Dilithium: Post-Quantum Digital Signature Algorithm](https://github.com/itzmeanjan/dilithium)\n- [SPHINCS+: Stateless Hash-based Digital Signature Algorithm](https://github.com/itzmeanjan/sphincs)\n- [Falcon: Fast-Fourier Lattice-based Compact Signatures over NTRU](https://github.com/itzmeanjan/falcon)\n- [FrodoKEM: Practical Quantum-secure Key Encapsulation from Generic Lattices](https://github.com/itzmeanjan/frodokem)\n- [Saber: Post-Quantum Key Encapsulation Mechanism](https://github.com/itzmeanjan/saber)\n\n\u003e [!WARNING]\n\u003e Above list may not be up-to-date !\n\nHere I'm maintaining a zero-dependency, header-only C++ library, using modern C++ features ( such as C++{\u003e=11} ), which is fairly easy-to-use in your project, implementing SHA3 [specification](https://dx.doi.org/10.6028/NIST.FIPS.202) i.e. NIST FIPS PUB 202.\n\n\u003e [!NOTE]\n\u003e All Sha3 hash functions and xofs are implemented as `constexpr` functions - meaning for any statically defined input message these functions can be evaluated in compile-time in constant-expression context. See [tests](./tests).\n\nFollowing algorithms ( with flexible interfaces ) are implemented in `sha3` library.\n\nAlgorithm | Input | Output | Behaviour | Namespace + Header\n--- | :-: | :-: | :-: | --:\nSHA3-224 | N ( \u003e=0 ) -bytes message | 28 -bytes digest | Given N -bytes input message, this routine computes 28 -bytes sha3-224 digest, while *(incrementally)* consuming message into Keccak[448] sponge. | [`sha3_224::sha3_224_t`](./include/sha3/sha3_224.hpp)\nSHA3-256 | N ( \u003e=0 ) -bytes message | 32 -bytes digest | Given N -bytes input message, this routine computes 32 -bytes sha3-256 digest, while *(incrementally)* consuming message into Keccak[512] sponge. | [`sha3_256::sha3_256_t`](./include/sha3/sha3_256.hpp)\nSHA3-384 | N ( \u003e=0 ) -bytes message | 48 -bytes digest | Given N -bytes input message, this routine computes 48 -bytes sha3-384 digest, while *(incrementally)* consuming message into Keccak[768] sponge. | [`sha3_384::sha3_384_t`](./include/sha3/sha3_384.hpp)\nSHA3-512 | N ( \u003e=0 ) -bytes message | 64 -bytes digest | Given N -bytes input message, this routine computes 64 -bytes sha3-512 digest, while *(incrementally)* consuming message into Keccak[1024] sponge. | [`sha3_512::sha3_512_t`](./include/sha3/sha3_512.hpp)\nSHAKE-128 | N ( \u003e=0 ) -bytes message | M ( \u003e=0 ) -bytes output | Given N -bytes input message, this routine squeezes arbitrary ( = M ) number of output bytes from Keccak[256] sponge, which has already *(incrementally)* absorbed input bytes. | [`shake128::shake128_t`](./include/sha3/shake128.hpp)\nSHAKE-256 | N ( \u003e=0 ) -bytes message | M ( \u003e=0 ) -bytes digest | Given N -bytes input message, this routine squeezes arbitrary ( = M ) number of output bytes from Keccak[512] sponge, which has already *(incrementally)* absorbed input bytes. | [`shake256::shake256_t`](./include/sha3/shake256.hpp)\n\nPerformance of SHA3 hash and extendable output functions on a `12th Gen Intel(R) Core(TM) i7-1260P`, running `Linux 6.11.0-18-generic` kernel, compiled with `GCC-14.2.0` with optimization options `-O3 -march=native -flto`.\n\n**SHA3 Hash Functions**\n\n| Algorithm    | Input Size (bytes) | MB/s (Median) |\n|--------------|--------------------|---------------|\n| SHA3-256     | 64                  | 483          |\n| SHA3-256     | 256                 | 700          |\n| SHA3-256     | 1024                | 644          |\n| SHA3-256     | 4096                | 642          |\n| SHA3-256     | 16384               | 655          |\n| SHA3-512     | 64                  | 602          |\n| SHA3-512     | 256                 | 367          |\n| SHA3-512     | 1024                | 330          |\n| SHA3-512     | 4096                | 335          |\n| SHA3-512     | 16384               | 339          |\n\n**SHA3 Extendable Output Functions**\n\n| Algorithm    | Input Size (bytes) | Output Size (bytes) | MB/s (Median) |\n|--------------|--------------------|----------------------|--------------|\n| SHAKE128     | 64                  | 64                    | 465        |\n| SHAKE128     | 256                 | 64                    | 698        |\n| SHAKE128     | 1024                | 64                    | 663        |\n| SHAKE128     | 4096                | 64                    | 706        |\n| SHAKE128     | 16384               | 64                    | 717        |\n| - | - | - | - |\n| SHAKE256     | 64                  | 64                    | 464        |\n| SHAKE256     | 256                 | 64                    | 699        |\n| SHAKE256     | 1024                | 64                    | 672        |\n| SHAKE256     | 4096                | 64                    | 638        |\n| SHAKE256     | 16384               | 64                    | 642        |\n\n## Prerequisites\n\n- A C++ compiler such as `g++`/ `clang++`, with support for C++20 standard library.\n\n```bash\n$ g++ --version\ng++ (Ubuntu 14.2.0-4ubuntu2) 14.2.0\n```\n\n- Build tools such as `cmake` and `make`.\n\n```bash\n$ make --version\nGNU Make 4.3\n\n$ cmake --version\ncmake version 3.25.1\n```\n\n- For testing SHA3 algorithms, you need to globally install `google-test` library and headers. Follow [this](https://github.com/google/googletest/tree/main/googletest#standalone-cmake-project) guide if you haven't installed it yet.\n- For benchmarking SHA3 algorithms, targeting CPU systems, `google-benchmark` library and headers are required to be installed system-wide. Follow [this](https://github.com/google/benchmark#installation) guide if you don't have it installed yet.\n\n\u003e [!NOTE]\n\u003e If you are on a machine running GNU/Linux kernel and you want to obtain CPU cycles or Cycles/ byte or instruction/ cycle etc., when benchmarking SHA3 algorithms, you should consider building `google-benchmark` library yourself with `libPFM` support, following the step-by-step guide @ https://gist.github.com/itzmeanjan/05dc3e946f635d00c5e0b21aae6203a7. Find more about libPFM @ https://perfmon2.sourceforge.net.\n\n\u003e [!TIP]\n\u003e Git submodule based dependencies will generally be imported automatically, but in case that doesn't work, you can manually bring them in by issuing `$ git submodule update --init` from inside the root of this repository.\n\n## Testing\n\nFor ensuring that SHA3 hash function and extendable output function implementations are correct \u0026 conformant to the NIST standard ( see https://dx.doi.org/10.6028/NIST.FIPS.202 ), I make use of K(nown) A(nswer) T(ests), generated following the gist @ https://gist.github.com/itzmeanjan/448f97f9c49d781a5eb3ddd6ea6e7364.\n\nI also test correctness of\n\n- Incremental message absorption property of SHA3 hash functions and Xofs.\n- Incremental output squeezing property of SHA3 Xofs.\n\nSome compile-time executed tests ( using `static_assert` ) are also implemented, which ensure that all Sha3 hash functions and xofs are `constexpr` - meaning they can be evaluated during compilation-time for any statically defined input message.\n\nIssue following command for running all the test cases.\n\n```bash\n# Shows help message - which targets are available and what do each of them do\nmake\n# or\nmake help\n\nmake test -j\nmake debug_asan_test -j\nmake debug_ubsan_test -j\nmake release_asan_test -j\nmake release_ubsan_test -j\n\n# Specify which compiler to use\nCXX=clang++ make test -j\n```\n\n```bash\nPASSED TESTS (18/18):\n       1 ms: build/test/test.out Sha3Hashing.CompileTimeEvalSha3_384\n       1 ms: build/test/test.out Sha3Xof.CompileTimeEvalShake256\n       1 ms: build/test/test.out Sha3Hashing.CompileTimeEvalSha3_512\n       2 ms: build/test/test.out Sha3Hashing.CompileTimeEvalSha3_256\n       2 ms: build/test/test.out Sha3Hashing.CompileTimeEvalSha3_224\n       4 ms: build/test/test.out Sha3Xof.CompileTimeEvalShake128\n       5 ms: build/test/test.out Sha3Hashing.Sha3_256KnownAnswerTests\n       6 ms: build/test/test.out Sha3Hashing.Sha3_224IncrementalAbsorption\n       7 ms: build/test/test.out Sha3Hashing.Sha3_512KnownAnswerTests\n       7 ms: build/test/test.out Sha3Xof.Shake128KnownAnswerTests\n       7 ms: build/test/test.out Sha3Hashing.Sha3_224KnownAnswerTests\n       7 ms: build/test/test.out Sha3Hashing.Sha3_512IncrementalAbsorption\n       7 ms: build/test/test.out Sha3Hashing.Sha3_256IncrementalAbsorption\n       7 ms: build/test/test.out Sha3Hashing.Sha3_384KnownAnswerTests\n       8 ms: build/test/test.out Sha3Xof.Shake256KnownAnswerTests\n       8 ms: build/test/test.out Sha3Hashing.Sha3_384IncrementalAbsorption\n    1028 ms: build/test/test.out Sha3Xof.Shake128IncrementalAbsorptionAndSqueezing\n    1112 ms: build/test/test.out Sha3Xof.Shake256IncrementalAbsorptionAndSqueezing\n```\n\n## Benchmarking\n\nFor benchmarking SHA3 hash and extendable output functions, targeting CPU systems, using `google-benchmark`, issue following command.\n\n\u003e [!CAUTION]\n\u003e You must disable CPU frequency scaling during benchmarking, following [this](https://github.com/google/benchmark/blob/4931aefb51d1e5872b096a97f43e13fa0fc33c8c/docs/reducing_variance.md) guide.\n\n\u003e [!NOTE]\n\u003e When benchmarking extendable output functions ( Xofs ), fixed length output of 32/ 64 -bytes are squeezed from sponge ( s.t. all output bytes are requested in a single call to the `squeeze` function ), for input message byte array of length N s.t. N = 2^i (i.e. power of 2).\n\n```bash\nmake perf -j      # You must issue this if you built your google-benchmark library with libPFM support.\nmake benchmark -j # Else you have to issue this one.\n```\n\n### On 12th Gen Intel(R) Core(TM) i7-1260P\n\nCompiled with `g++ (Ubuntu 14.2.0-4ubuntu2) 14.2.0` while running on `Linux 6.11.0-18-generic x86_64`.\n\nI maintain benchmark results in JSON format @ [bench_result_on_Linux_6.11.0-18-generic_x86_64_with_g++_14](./bench_result_on_Linux_6.11.0-18-generic_x86_64_with_g++_14.json).\n\n### On Apple M1 Max\n\nCompiled with `Apple Clang version 16.0.0` while running kernel `Darwin 24.1.0 arm64`.\n\nMaintaining benchmark results in JSON format @ [bench_result_on_Darwin_24.3.0_arm64_with_c++_16.0.0](./bench_result_on_Darwin_24.3.0_arm64_with_c++_16.0.0.json).\n\n## Usage\n\n`sha3` - C++ header-only library is written such that it's fairly easy for one to start using it in their project. All one needs to do\n\n- Include proper header files ( select which scheme you need by name ).\n- Use proper struct(s)/ API(s)/ constant(s) ( see [usage examples](./examples) or [test cases](./tests/) ).\n- When compiling, let your compiler know where it can find respective header files, which is `./include` directory.\n\nScheme | Header | Namespace | Example\n--- | --- | --- | --:\nSHA3-224 | ./include/sha3/sha3_224.hpp | `sha3_224::` | [examples/sha3_224.cpp](./examples/sha3_224.cpp)\nSHA3-256 | ./include/sha3/sha3_256.hpp | `sha3_256::` | [examples/sha3_256.cpp](./examples/sha3_256.cpp)\nSHA3-384 | ./include/sha3/sha3_384.hpp | `sha3_384::` | [examples/sha3_384.cpp](./examples/sha3_384.cpp)\nSHA3-512 | ./include/sha3/sha3_512.hpp | `sha3_512::` | [examples/sha3_512.cpp](./examples/sha3_512.cpp)\nSHAKE128 | ./include/sha3/shake128.hpp | `shake128::` | [examples/shake128.cpp](./examples/shake128.cpp)\nSHAKE256 | ./include/sha3/shake256.hpp | `shake256::` | [examples/shake256.cpp](./examples/shake256.cpp)\n\nAs this library implements all Sha3 hash functions and xofs as `constexpr` - one can evaluate, say Sha3-256 digest of some statically defined input message, during program compilation time. Let's see how to do that and for ensuring that it computes correct message digest, we'll use static assertions.\n\n```cpp\n#include \"sha3/sha3_256.hpp\"\n#include \u003cnumeric\u003e\n\n// Eval SHA3-256 hash on statically defined input message during compilation-time.\nconstexpr std::array\u003cuint8_t, sha3_256::DIGEST_LEN\u003e\neval_sha3_256()\n{\n  // Statically defined input.\n  std::array\u003cuint8_t, sha3_256::DIGEST_LEN * 2\u003e data{};\n  std::iota(data.begin(), data.end(), 0);\n\n  // To be computed output.\n  std::array\u003cuint8_t, sha3_256::DIGEST_LEN\u003e md{};\n\n  sha3_256::sha3_256_t hasher;\n  hasher.absorb(data);\n  hasher.finalize();\n  hasher.digest(md);\n\n  return md;\n}\n\nint\nmain()\n{\n\n  // Input  = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f\n  // Output = c8ad478f4e1dd9d47dfc3b985708d92db1f8db48fe9cddd459e63c321f490402\n  constexpr auto md = eval_sha3_256();\n  static_assert(md ==\n                  std::array\u003cuint8_t, sha3_256::DIGEST_LEN\u003e{\n                    200, 173, 71, 143, 78, 29,  217, 212, 125, 252, 59,\n                    152, 87,  8,  217, 45, 177, 248, 219, 72,  254, 156,\n                    221, 212, 89, 230, 60, 50,  31,  73,  4,   2 },\n                \"Must be able to compute Sha3-256 hash during compile-time !\");\n\n  return 0;\n}\n```\n\nI maintain examples of using Sha3 hash function and xof API, inside [examples](./examples/) directory. Run them all by issuing\n\n```bash\nmake example -j\n```\n\n```bash\nSHA3-224\n\nInput  : 2c85bd27e447424ffecd668a690d385304553230e898e50e1bbda2035a852a3c\nOutput : a39d989bab91337bcc2af474aa6235a3ab05680c0d4cd02e5243b7cd\n--- --- ---\nSHA3-256\n\nInput  : 5753f01c245b2cc4417850703e6cbeed822870a2b8f8144c2c30b35d2f9be2db\nOutput : c54d90ded2536dce8a73d06f474cdfd3cf14ddaaf54c0c2598347304e5fcb208\n--- --- ---\nSHA3-384\n\nInput  : 0633acdbe5f78361622e4fefa816a41af0705f0d6e5e14cf339127e035275e11\nOutput : 18094d6c42a25e8f64357f834f8f7d64ac456b32fc1bc09fd3084565f7b4e9eae8ada85adb6be35f89effedcdf84831a\n--- --- ---\nSHA3-512\n\nInput  : 9c3679d1a7ba47a5fb7cd05fa60fe05939e6bf267b7e4b95c1b7a306ee83d5d0\nOutput : 31e4c24bf38c287ba66f992b7bddebf99bfe6dca03830e9845880af5019a02aa32e1e5aef47cec902731d0b83815a5faed3ecabc44b68082bbd199a12b40579c\n--- --- ---\nSHAKE-128\n\nInput  : 09ad8b662f1e7c1fc151f2b896a33d22695a6e1e67e316bd4953c3475a8bd6b3\nOutput : b7e3784fa89e4c9edd7eacd6e3ffa67c7032b22fbf31c58a7f0b268b0040c9099607a7ac68cc8722\n--- --- ---\nSHAKE-256\n\nInput  : 5f6b6c5c905cca71d9f83cd90b7db3a4f4ca5303e97e25e343e2c829ae0ce7c3\nOutput : be24aea2c7d7488d28d638ee46baba5474994171b6bc42fce59679f5578e57ac59f4521cbeb88bd5\n--- --- ---\n```\n\n\u003e [!NOTE]\n\u003e This library doesn't expose any raw pointer + length -based interfaces, rather everything is wrapped under much safer `std::span` - which one can easily create from `std::{array, vector}` or even raw pointers and length pair. See https://en.cppreference.com/w/cpp/container/span. I made this choice because this gives us much better type safety and compile-time error reporting.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fitzmeanjan%2Fsha3","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fitzmeanjan%2Fsha3","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fitzmeanjan%2Fsha3/lists"}