{"id":25654327,"url":"https://github.com/pauldreik/lemac","last_synced_at":"2026-06-21T14:31:28.248Z","repository":{"id":275491640,"uuid":"926194287","full_name":"pauldreik/lemac","owner":"pauldreik","description":"C++ implementation of the lemac hash by Augustin Bariant","archived":false,"fork":false,"pushed_at":"2025-06-16T19:26:46.000Z","size":141,"stargazers_count":2,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-16T19:41:41.826Z","etag":null,"topics":["cryptography","hashing"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsl-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pauldreik.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,"zenodo":null}},"created_at":"2025-02-02T19:14:46.000Z","updated_at":"2025-06-16T18:51:28.000Z","dependencies_parsed_at":null,"dependency_job_id":"dc37d67a-371b-478a-808b-8a35c3bcf61c","html_url":"https://github.com/pauldreik/lemac","commit_stats":null,"previous_names":["pauldreik/lemac"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/pauldreik/lemac","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pauldreik%2Flemac","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pauldreik%2Flemac/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pauldreik%2Flemac/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pauldreik%2Flemac/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pauldreik","download_url":"https://codeload.github.com/pauldreik/lemac/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pauldreik%2Flemac/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34613048,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-21T02:00:05.568Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["cryptography","hashing"],"created_at":"2025-02-23T20:19:42.727Z","updated_at":"2026-06-21T14:31:28.243Z","avatar_url":"https://github.com/pauldreik.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Lemac\n\nThis is a C++ implementation of the [lemac cryptographic hash](https://doi.org/10.46586/tosc.v2024.i2.35-67) by Augustin Bariant.\n\nLemac is very interesting because it utilizes AES hardware acceleration which is very common.\n\nThe AESNI implementation is based on the public domain code in [https://github.com/AugustinBariant/Implementations_LeMac_PetitMac/](https://github.com/AugustinBariant/Implementations_LeMac_PetitMac/) but has been heavily modified to use C++ and run clean with sanitizers.\n\n# Performance\n\nThe bulk speed on a single core is up to about\n\n  * 77 GiB/s, 0.067 cycles per byte (AMD zen 4, Debian 13 Trixie)\n  * 48 GiB/s (Apple M4 MacBook Air, macos) \n  * 11 GiB/s, 0.19 cycles per byte (raspberry pi 5, Ubuntu 24.04)\n\nThe speed is measured with the included benchmark and using `perf stat` to get the average clock frequency during the test. To build and run the benchmark:\n\n    cmake -B build-release -S . -DCMAKE_BUILD_TYPE=Release\n    cmake --build build-release\n    build-release/benchmark/benchmark\n\n## Performance characteristics\n\nThe cost of the hash is divided into\n\n 1. Initialization (cost is roughly equivalent to hashing 5 kB of extra data) \n 2. Hashing\n 3. Finalization (cost is roughly equivalent to hashing 2 kB of extra data)\n\nThe initialization cost can mostly be avoided by either reusing an existing hasher object (using `.reset()` followed by `.update()` and `.finalize()`) or simply instantiate one object and copy it before each hash operation.\n\nIf all data to be hashed is known up front, the `oneshot()` function is more efficient to use than `update()` followed by `finalize()`.\n\n## Results on AMD zen4\n\nMeasurements on an AMD Ryzen 9 7950X3D:\n * lemac 256 kB, oneshot 76.7 GiB/s (median of 5)\n * lemac 1 MB, oneshot 74.3 GiB/s (median of 5)\n * lemac 256 kB, update+finalize 76.6 GiB/s (median of 5)\n * lemac 1 MB, update+finalize 74.3 GiB/s (median of 5)\n\nThis can be compared with some other interesting hashes\n * the non-cryptographic [xxh3/xxh128 hashes](https://xxhash.com/) reaches about 89 GiB/s, measured with`xxhsum -b`.  This is about 16% faster than lemac.\n * the non-cryptographic [clhash](https://github.com/simdhash/clhash) which reaches 0.11 cycles per byte using the provided benchmark, which is about 39% slower than lemac.\n * SHA1 measured with `openssl speed -evp SHA1` reaches about 2.8 GiB/s \n\nThe AES performance, as measured by `openssl speed -evp AES-128-ECB` is about 16.4 GiB/s.\n\n## Results on an Apple M4 MacBook Air\n\nHere are the results from a single run with default power settings plugged in to the charger, if that matters. There is some run to run variation, take this with a grain of salt.\n\n```\ncompiler: clang\nwith       1 byte at a time and strategy  update_and_finalize: hashed with  0.038 GiB/s  0.027 µs/hash\nwith    1024 byte at a time and strategy  update_and_finalize: hashed with 23.408 GiB/s  0.044 µs/hash\nwith   16384 byte at a time and strategy  update_and_finalize: hashed with 45.351 GiB/s  0.361 µs/hash\nwith  262144 byte at a time and strategy  update_and_finalize: hashed with 47.915 GiB/s  5.471 µs/hash\nwith 1048576 byte at a time and strategy  update_and_finalize: hashed with 47.990 GiB/s 21.850 µs/hash\nwith       1 byte at a time and strategy              oneshot: hashed with  0.021 GiB/s  0.049 µs/hash\nwith    1024 byte at a time and strategy              oneshot: hashed with 17.128 GiB/s  0.060 µs/hash\nwith   16384 byte at a time and strategy              oneshot: hashed with 43.223 GiB/s  0.379 µs/hash\nwith  262144 byte at a time and strategy              oneshot: hashed with 47.394 GiB/s  5.531 µs/hash\nwith 1048576 byte at a time and strategy              oneshot: hashed with 47.653 GiB/s 22.005 µs/hash\n```\n## Results on an Apple M3 MacBook Air\n\nHere are the results from a single run with default power settings plugged in to the charger, if that matters. There is some run to run variation, take this with a grain of salt.\n\n```\ncompiler: clang\nwith       1 byte at a time and strategy update_and_finalize : hashed with  0.042 GiB/s  0.024 µs/hash\nwith    1024 byte at a time and strategy update_and_finalize : hashed with 24.588 GiB/s  0.042 µs/hash\nwith   16384 byte at a time and strategy update_and_finalize : hashed with 42.378 GiB/s  0.387 µs/hash\nwith  262144 byte at a time and strategy update_and_finalize : hashed with 43.691 GiB/s  6.000 µs/hash\nwith 1048576 byte at a time and strategy update_and_finalize : hashed with 43.854 GiB/s 23.911 µs/hash\nwith       1 byte at a time and strategy oneshot             : hashed with  0.021 GiB/s  0.049 µs/hash\nwith    1024 byte at a time and strategy oneshot             : hashed with 16.297 GiB/s  0.063 µs/hash\nwith   16384 byte at a time and strategy oneshot             : hashed with 39.348 GiB/s  0.416 µs/hash\nwith  262144 byte at a time and strategy oneshot             : hashed with 43.242 GiB/s  6.062 µs/hash\nwith 1048576 byte at a time and strategy oneshot             : hashed with 43.577 GiB/s 24.062 µs/hash\n```\n\n## Results on Raspberry Pi 5\n\nThis was measured on Ubuntu 24.04. Unfortunately, this was measured with insufficient cooling and the average clock speed was 2.263 GHz according to perf stat.\n\n * lemac 256 kB, oneshot 11.4 GiB/s (median of 7)\n * lemac 1 MB, oneshot 11.5 GiB/s (median of 7)\n * lemac 256 kB, update+finalize 11.0 GiB/s (median of 7)\n * lemac 1 MB, update+finalize 10.6 GiB/s (median of 7)\n\nThe non-cryptographic xxh reaches about 13.2 GiB/s on the same system.\n\nThe AES performance, as measured by `openssl speed -evp AES-128-ECB` is about 3.4 GiB/s.\n\n# Hardware and OS support\n\nThe code requires C++20. amd64 (AES-NI) is supported (most current desktop cpus), as well as arm64 with cryptographic extensions (like the current apple hardware and raspberry pi 5). Support for other architectures is planned by providing a non-accelerated fallback implementation.\n\n## Linux\nThe code runs with clang(\u003e=16) and gcc (\u003e=12). It may work with earlier compiler versions, but those are not tested in CI.\n\n## Apple\nThe code works on apple with xcode and current hardware (apple silicon).\nApple M1, M3 and M4 have been tested successfully. No tests have been made with the older apple x86 platforms (if you have tested this, please report how it went!).\n\n## Windows\nBoth amd64 and arm64 are supported. On arm64, there is currently no runtime check for hardware support, it is hard coded to always on.\n\n# Usage\n\n## Command line tool lemacsum\n\nAfter compilation, there is a binary **lemacsum** which works in similar spirit to sha256sum, xxhsum,  b3sum etc.\n\nGenerate a checksum:\n\n    $ lemacsum file |tee checksum\n    5351314614a6de5f31704434c083e7a9  file\n\nVerify a checksum:\n\n    $ lemacsum -c checksum\n    file: OK\n\n\n## As a library\n\nTo use this from cmake, add the following snippet to your CMakeLists.txt:\n\n```cmake\ninclude(FetchContent)\nFetchContent_Declare(\n  lemac\n  GIT_REPOSITORY https://github.com/pauldreik/lemac.git\n  GIT_TAG        main\n)\nFetchContent_MakeAvailable(lemac)\ntarget_link_libraries(my_executable PRIVATE lemac)\n```\n\nand in your code, using fmt for the nice printout:\n\n```cpp\n#include \u003cstring\u003e\n#include \u003cfmt/ranges.h\u003e\n#include \"lemac.h\"\n\nint main()\n{\n  std::string message(\"hello\");\n  lemac::LeMac lm;\n  const auto hash = lm.oneshot(\n      std::span((const std::uint8_t*)message.data(), message.size()));\n\n  fmt::println(\"the hash of {} is {:02x}\", message, fmt::join(hash, \"\"));\n  // prints \"the hash of hello is b2e64fbf9da60940f54a4cd3ee07c37d\"\n}\n```\n\n# License\n\nBoost 1.0 license, which allows commercial use and modification.\n\n# Quality\n\nThe goals are (in order)\n\n 1. correctness\n 2. run clean with both undefined and address sanitizers\n 3. performance\n 4. readability and maintainability\n 5. portability\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpauldreik%2Flemac","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpauldreik%2Flemac","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpauldreik%2Flemac/lists"}