diff --git a/.env.template b/.env.template new file mode 100644 index 0000000..a8c91fa --- /dev/null +++ b/.env.template @@ -0,0 +1,5 @@ +DB_NAME= +DB_USER= +DB_PASSWORD= +DB_HOST= +DB_PORT= \ No newline at end of file diff --git a/.gitattributes b/.gitattributes index 0c0a3b9..adfc447 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,2 @@ generated/** linguist-generated +ext/** linguist-vendored \ No newline at end of file diff --git a/.github/actions/install-postgres/action.yml b/.github/actions/install-postgres/action.yml new file mode 100644 index 0000000..101c0eb --- /dev/null +++ b/.github/actions/install-postgres/action.yml @@ -0,0 +1,27 @@ +name: 'Install PostgreSQL' +description: 'Install PostgreSQL and its dependencies for each os' + +runs: + using: "composite" + steps: + - name: Install PostgreSQL on Linux + shell: bash + if: runner.os == 'Linux' + run: | + sudo apt-get update + sudo apt-get install -y postgresql + sudo service postgresql start + + - name: Install PostgreSQL on macOS + shell: bash + if: runner.os == 'macOS' + run: | + brew update + brew install postgresql + brew services start postgresql + + - name: Install PostgreSQL on Windows + shell: bash + if: runner.os == 'Windows' + run: | + choco install postgresql --version=17 -y \ No newline at end of file diff --git a/.github/actions/process-artifacts/action.yml b/.github/actions/process-artifacts/action.yml index 97df6a7..182ce50 100644 --- a/.github/actions/process-artifacts/action.yml +++ b/.github/actions/process-artifacts/action.yml @@ -8,7 +8,7 @@ runs: shell: bash if: runner.os == 'macOS' run: | - sed -i '' -e "s/oop/${EXECUTABLE_NAME}/" "${{ env.ZIP_NAME }}/launcher.command" + sed -i '' -e "s/oop/${{ env.SRC_EXECUTABLE_NAME }}/" "${{ env.ZIP_NAME }}/launcher.command" chmod +x "${{ env.ZIP_NAME }}/launcher.command" - name: Copy missing dylibs @@ -19,7 +19,7 @@ runs: if [[ "${BUILD_TYPE}" =~ "Deb" ]]; then mkdir lib # cp /Library/Developer/CommandLineTools/usr/lib/clang/16/lib/darwin/libclang_rt.asan_osx_dynamic.dylib lib - # install_name_tool -change @rpath/libclang_rt.asan_osx_dynamic.dylib @executable_path/lib/libclang_rt.asan_osx_dynamic.dylib ${{ env.ZIP_NAME }}/${{ env.EXECUTABLE_NAME }} + # install_name_tool -change @rpath/libclang_rt.asan_osx_dynamic.dylib @executable_path/lib/libclang_rt.asan_osx_dynamic.dylib ${{ env.ZIP_NAME }}/${{ env.SRC_EXECUTABLE_NAME }} mv lib ${{ env.ZIP_NAME }}/ fi @@ -29,8 +29,8 @@ runs: run: | mkdir lib cp /opt/homebrew/lib/gcc/13/libstdc++.6.dylib /opt/homebrew/lib/gcc/13/libgcc_s.1.1.dylib lib - install_name_tool -change /opt/homebrew/lib/gcc/13/libstdc++.6.dylib @executable_path/lib/libstdc++.6.dylib ${{ env.ZIP_NAME }}/${{ env.EXECUTABLE_NAME }} - install_name_tool -change /opt/homebrew/lib/gcc/13/libgcc_s.1.1.dylib @executable_path/lib/libgcc_s.1.1.dylib ${{ env.ZIP_NAME }}/${{ env.EXECUTABLE_NAME }} + install_name_tool -change /opt/homebrew/lib/gcc/13/libstdc++.6.dylib @executable_path/lib/libstdc++.6.dylib ${{ env.ZIP_NAME }}/${{ env.SRC_EXECUTABLE_NAME }} + install_name_tool -change /opt/homebrew/lib/gcc/13/libgcc_s.1.1.dylib @executable_path/lib/libgcc_s.1.1.dylib ${{ env.ZIP_NAME }}/${{ env.SRC_EXECUTABLE_NAME }} mv lib ${{ env.ZIP_NAME }}/ - name: Copy missing dlls diff --git a/.github/actions/runtime-checks/action.yml b/.github/actions/runtime-checks/action.yml index 794e2ad..7801ad5 100644 --- a/.github/actions/runtime-checks/action.yml +++ b/.github/actions/runtime-checks/action.yml @@ -49,7 +49,7 @@ runs: # env: # ASAN_OPTIONS: detect_leaks=1 run: | - cat "${INPUT_FILENAME}" | tr -d '\r' | ./${{ env.ZIP_NAME }}/"${EXECUTABLE_NAME}" + cat "${INPUT_FILENAME}" | tr -d '\r' | ./${{ env.ZIP_NAME }}/${{ env.SRC_EXECUTABLE_NAME }} - name: Sanitizers (Windows MSVC) shell: bash @@ -57,7 +57,7 @@ runs: if: matrix.cxx == 'cl' && matrix.runs_asan == true continue-on-error: true run: | - cat "${INPUT_FILENAME}" | ./${{ env.ZIP_NAME }}/"${EXECUTABLE_NAME}".exe + cat "${INPUT_FILENAME}" | ./${{ env.ZIP_NAME }}/${{ env.SRC_EXECUTABLE_NAME }}.exe - name: Valgrind shell: bash @@ -67,4 +67,4 @@ runs: cat "${INPUT_FILENAME}" | tr -d '\r' | valgrind \ --leak-check=full --show-leak-kinds=all --track-origins=yes \ --error-exitcode=1 \ - ./${{ env.ZIP_NAME }}/"${EXECUTABLE_NAME}" + ./${{ env.ZIP_NAME }}/${{ env.SRC_EXECUTABLE_NAME }} diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index e515408..7f621ef 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -2,10 +2,11 @@ name: C++ CI on: push: - branches: ['*'] # NOTE: replace/update with appropriate branch name(s) - tags: ['*'] + branches: [ '*' ] # NOTE: replace/update with appropriate branch name(s) + tags: [ '*' ] pull_request: - branches: ['*'] # NOTE: replace/update with appropriate branch name(s) + types: [closed] + branches: [ '*' ] # NOTE: replace/update with appropriate branch name(s) workflow_dispatch: inputs: build_type: @@ -21,14 +22,20 @@ on: env: BUILD_TYPE: ${{ inputs.build_type || 'Debug' }} - # NOTE: update executable name if it is changed in CMakeLists.txt - EXECUTABLE_NAME: "Password-Keeper" + SRC_EXECUTABLE_NAME: "Password-Keeper-src" + TEST_EXECUTABLE_NAME: "Password-Keeper-Test-Runner" INPUT_FILENAME: "tastatura.txt" BIN_DIR: "bin" # update in cmake/Options.cmake:6 if changing name here BUILD_DIR: "build" EXT_DIR: "ext" GEN_DIR: "generated" + DB_NAME: ${{ secrets.DB_NAME }} + DB_USER: ${{ secrets.DB_USER }} + DB_PASSWORD: ${{ secrets.DB_PASSWORD }} + DB_HOST: ${{ secrets.DB_HOST }} + DB_PORT: ${{ secrets.DB_PORT }} + defaults: run: # Use a bash shell, so we can use the same syntax for environment variable @@ -75,7 +82,7 @@ jobs: # concurrency: # group: ${{ matrix.name }} runs-on: ${{ matrix.os }} - timeout-minutes: 8 + timeout-minutes: 15 permissions: attestations: write contents: write @@ -100,16 +107,16 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-22.04 - c: clang-18 - cxx: clang++-18 - clang_ver: "18" - clang_ver_full: "18.1.8" - name: "MSan: Ubuntu 22.04 Clang 18" - cmake_flags: "-DUSE_MSAN=ON" - cmake_generator: Ninja - # This env runs memory sanitizers - runs_msan: true +# - os: ubuntu-22.04 +# c: clang-18 +# cxx: clang++-18 +# clang_ver: "18" +# clang_ver_full: "18.1.8" +# name: "MSan: Ubuntu 22.04 Clang 18" +# cmake_flags: "-DUSE_MSAN=ON" +# cmake_generator: Ninja +# # This env runs memory sanitizers +# runs_msan: true - os: ubuntu-22.04 c: gcc-12 @@ -147,16 +154,16 @@ jobs: # cmake_flags: # cmake_generator: Ninja - - os: windows-2022 - c: cl - cxx: cl - name: "ASan: Windows 2022 MSVC 19.41" - cmake_flags: "-DUSE_ASAN=ON" - # Ninja is not faster on MSVC because... MSVC - # cmake_generator: "Ninja" - # cmake_generator: "Ninja Multi-Config" - # This env runs address sanitizers - runs_asan: true +# - os: windows-2022 +# c: cl +# cxx: cl +# name: "ASan: Windows 2022 MSVC 19.41" +# cmake_flags: "-DUSE_ASAN=ON" +# # Ninja is not faster on MSVC because... MSVC +# # cmake_generator: "Ninja" +# # cmake_generator: "Ninja Multi-Config" +# # This env runs address sanitizers +# runs_asan: true - os: windows-2022 c: gcc @@ -169,6 +176,9 @@ jobs: - name: Checkout repo uses: actions/checkout@v4 + - name: Install PostgreSQL + uses: ./.github/actions/install-postgres + - name: Set timestamp and zip name run: | echo "TIMESTAMP=$(date +%Y-%m-%d-%H-%M-%S)" >> ${GITHUB_ENV} @@ -188,7 +198,6 @@ jobs: with: custom_flags: ${{ matrix.cmake_flags }} warnings_as_errors: 'ON' - - name: Build run: | bash ./scripts/cmake.sh build -t ${{ env.BUILD_TYPE }} @@ -213,10 +222,78 @@ jobs: name: ${{ env.ZIP_NAME }}_${{ env.TIMESTAMP }} path: ${{ env.ZIP_NAME }} retention-days: 30 - - name: Runtime checks uses: ./.github/actions/runtime-checks - name: Create release uses: ./.github/actions/create-release if: startsWith(github.ref, 'refs/tags/') + + test: + name: "Test" + runs-on: ubuntu-latest + needs: build + timeout-minutes: 5 + services: + postgres: + image: postgres:latest + env: + POSTGRES_USER: pipeline_test_user + POSTGRES_PASSWORD: pipeline_test_password + POSTGRES_DB: pipeline_test_password_keeper + options: >- + --health-cmd "pg_isready -U pipeline_test_user" + --health-interval 10s + --health-timeout 5s + --health-retries 5 + ports: + - 5432:5432 + env: + DB_HOST: localhost + DB_NAME: pipeline_test_password_keeper + DB_USER: pipeline_test_user + DB_PASSWORD: pipeline_test_password + DB_PORT: 5432 + RUNS_TESTS: 1 + + steps: + - name: "Checkout code" + uses: actions/checkout@v4 + + - name: "Set up GCC" + run: sudo apt-get install -y build-essential gcc + + - name: "Install dependencies" + run: | + sudo apt-get update + sudo apt-get install -y postgresql + + - name: "Install CMake and Ninja" + run: | + sudo apt-get install -y cmake ninja-build + + - name: "Build project" + run: | + cmake -S . -B build -G Ninja -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12 -DRUN_TESTS=ON -DSKIP_BUILD_TEST=ON + cmake --build build + + - name: "Postgres setup" + run: | + export PGPASSWORD=pipeline_test_password + psql -h localhost -U pipeline_test_user -d pipeline_test_password_keeper -c "CREATE TABLE IF NOT EXISTS users ( + id SERIAL PRIMARY KEY, + username VARCHAR(50) UNIQUE NOT NULL, + passwordSalt VARCHAR(150) NOT NULL, + passwordHash VARCHAR(150) NOT NULL + );" + + - name: "Run tests" + env: + DB_HOST: ${{ env.DB_HOST }} + DB_NAME: ${{ env.DB_NAME }} + DB_USER: ${{ env.DB_USER }} + DB_PASSWORD: ${{ env.DB_PASSWORD }} + DB_PORT: ${{ env.DB_PORT }} + run: | + cd build + ctest --verbose --no-compress-output diff --git a/.gitignore b/.gitignore index 0e8b168..a7a1424 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,9 @@ # Created by https://www.toptal.com/developers/gitignore/api/c++,clion,cmake,codeblocks,emacs,gcov,sublimetext,vim,visualstudio,visualstudiocode,xcode # Edit at https://www.toptal.com/developers/gitignore?templates=c++,clion,cmake,codeblocks,emacs,gcov,sublimetext,vim,visualstudio,visualstudiocode,xcode +# Environment file - contains secrets +*.env + ### C++ ### # Prerequisites *.d diff --git a/.idea/.name b/.idea/.name index d85a74a..0b0dc67 100644 --- a/.idea/.name +++ b/.idea/.name @@ -1 +1 @@ -oop \ No newline at end of file +PasswordKeeper \ No newline at end of file diff --git a/.idea/editor.xml b/.idea/editor.xml index 95d51a7..1f0ef49 100644 --- a/.idea/editor.xml +++ b/.idea/editor.xml @@ -1,580 +1,580 @@ + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 86bfbea..0b76fe5 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,12 +1,5 @@ - - diff --git a/.idea/runConfigurations/Run_Database.xml b/.idea/runConfigurations/Run_Database.xml new file mode 100644 index 0000000..47cb75a --- /dev/null +++ b/.idea/runConfigurations/Run_Database.xml @@ -0,0 +1,11 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/sqldialects.xml b/.idea/sqldialects.xml new file mode 100644 index 0000000..6c9a15b --- /dev/null +++ b/.idea/sqldialects.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index a3c7f94..c53fab3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,83 +1,33 @@ cmake_minimum_required(VERSION 3.26) - -# NOTE: update executable name in .github/workflows/cmake.yml:25 when changing executable name in this file -# for now, the project name is used as the executable name -project(Password-Keeper) -# set(CMAKE_PROJECT_VERSION_MAJOR 0) -# set(CMAKE_PROJECT_VERSION_MINOR 0) -# set(CMAKE_PROJECT_VERSION_PATCH 1) +project(PasswordKeeper) set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_VERBOSE_MAKEFILE ON) -include(cmake/Options.cmake) - -############################################################################### - -# external dependencies with FetchContent -# include(FetchContent) -# -# set(FETCHCONTENT_QUIET OFF) -# set(FETCHCONTENT_UPDATES_DISCONNECTED ON) -# -# NOTE: Also update env vars used for caching in -# - .github/actions/configure-cmake/action.yml -# - .github/workflows/cmake.yml -# FetchContent_Declare( -# SomeLib -# GIT_REPOSITORY https://github.com//.git -# GIT_TAG # > -# GIT_SHALLOW 1 # works only with branches or tags, not with arbitrary commit hashes -# ) -# -# FetchContent_MakeAvailable(SomeLib) - -#include(FetchContent) -# -#FetchContent_Declare( -# libpqxx -# GIT_REPOSITORY https://github.com/jtv/libpqxx.git -# GIT_TAG 7.9.2 -#) -#FetchContent_MakeAvailable(libpqxx) +set(PROJECT_ROOT "${CMAKE_CURRENT_LIST_DIR}") +set(CMAKE_HELPER_DIR "${PROJECT_ROOT}/cmake") +include(${CMAKE_HELPER_DIR}/Options.cmake) +include(${CMAKE_HELPER_DIR}/CopyHelper.cmake) -############################################################################### +include(FetchContent) -# external dependencies with find_package +set(FETCHCONTENT_QUIET OFF) +set(FETCHCONTENT_UPDATES_DISCONNECTED ON) -# find_package(Threads REQUIRED) -find_package(PkgConfig REQUIRED) -pkg_check_modules(PQ REQUIRED libpq) -pkg_check_modules(PQXX REQUIRED libpqxx) - -############################################################################### -# NOTE: update executable name in .github/workflows/cmake.yml:25 when changing name here -add_executable(${PROJECT_NAME} - main.cpp +FetchContent_Declare( + pqxx + GIT_REPOSITORY https://github.com/jtv/libpqxx.git + GIT_TAG 7.9.2 ) +FetchContent_MakeAvailable(pqxx) -include(cmake/CompilerFlags.cmake) - -############################################################################### -target_include_directories(${PROJECT_NAME} SYSTEM PRIVATE infrastructure) -target_include_directories(${PROJECT_NAME} PRIVATE ${PQ_INCLUDE_DIRS} ${PQXX_INCLUDE_DIRS}) -target_link_libraries(${PROJECT_NAME} PRIVATE ${PQ_LIBRARIES} ${PQXX_LIBRARIES}) -# use SYSTEM so cppcheck and clang-tidy do not report warnings from these directories -# target_include_directories(${PROJECT_NAME} SYSTEM PRIVATE ext//include) -# target_include_directories(${PROJECT_NAME} SYSTEM PRIVATE ${_SOURCE_DIR}/include) -# target_link_directories(${PROJECT_NAME} PRIVATE ${_BINARY_DIR}/lib) -# target_link_libraries(${PROJECT_NAME} ) - -############################################################################### -# copy binaries to "bin" folder; these are uploaded as artifacts on each release -# DESTINATION_DIR is set as "bin" in cmake/Options.cmake:6 -install(TARGETS ${PROJECT_NAME} DESTINATION ${DESTINATION_DIR}) -if(APPLE) - install(FILES launcher.command DESTINATION ${DESTINATION_DIR}) -endif() +find_package(PostgreSQL) -include(cmake/CopyHelper.cmake) -copy_files(FILES tastatura.txt) -# copy_files(FILES tastatura.txt config.json DIRECTORY images sounds) -# copy_files(DIRECTORY images sounds) +add_subdirectory(src) +if(RUN_TESTS) + include(CTest) + enable_testing() + add_subdirectory(tests) +endif () \ No newline at end of file diff --git a/README.md b/README.md index f15c0de..63d2b49 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,71 @@ +[ENG] +# Password-Keeper +## Project Description +The Password Keeper application enables users to manage their passwords in a secure database. +It offers functionality to efficiently and safely store and organize passwords, as well as the option to generate new, customized passwords on demand. + +## Notes +1. PostgreSQL Installation: + - To build the project, you must first install [PostgreSQL](https://www.postgresql.org/download/) on your computer. +2. Running the Application Locally: + - To use the application locally, you need to install [Docker](https://docs.docker.com/engine/install/), use the command + `docker compose up` in the project's [infrastructure](./infrastructure) folder, and create a new file named `.env` in the src folder. + Fill this file with the details from [compose.yml](./infrastructure/compose.yaml) , following the format described in the .env.template file. +3. Running Tests: + - To run the tests, add either the env.bat or env.sh file (the former for Windows, the latter for POSIX systems) + to the environment file settings of your toolchain (File | Settings | Build, Execution, Deployment | Toolchains) under the Environment File section. + Tests can be run either by executing the cmake-build-debug/tests/Password-Keeper-Test-Runner file or by running the ctest command in the cmake-build-debug folder. + +## CI/CD Pipeline +The CI/CD pipeline is configured in GitHub Actions and includes multiple stages to ensure code quality, compatibility, and functionality across various platforms. + +1. Code Quality Validation: + - The first two stages validate code correctness and ensure no warnings are generated (using Cppcheck and Clang-Tidy). + +2. Compatibility Testing Across Multiple Operating Systems: + - The next five stages ensure proper code execution on major operating systems (Linux, macOS, and Windows) and perform memory checks using MSAN, ASAN, and Valgrind to identify potential memory leaks and other memory-related issues. + +3. Functional Test Execution: + - The final stage runs functional tests to verify that the application behaves as expected. + +In all stages involving the execution of the application, a PostgreSQL service is included to ensure proper application functionality. + +[RO] # Password-Keeper ## Descriere proiect -AplicaÈ›ia este un Password Keeper care permite utilizatorilor să își gestioneze parolele într-o bază de date securizată. Aceasta oferă funcÈ›ionalitatea de a stoca È™i organiza parolele într-un mod eficient È™i sigur, precum È™i opÈ›iunea de a genera parole noi, personalizate, la cerere. + +AplicaÈ›ia este un Password Keeper care permite utilizatorilor să își gestioneze parolele într-o bază de date securizată. +Aceasta oferă funcÈ›ionalitatea de a stoca È™i organiza parolele într-un mod eficient È™i sigur, precum È™i opÈ›iunea de a +genera parole noi, personalizate, la cerere. ## Mentiuni -In acest moment proiectul poate fi construit numai folosind WSL. +1. Instalare PostgreSQL: + - Pentru a construi proiectul trebuie sa instalati mai intai [PostgreSQL](https://www.postgresql.org/download/) pe + calculatorul dumneavoastra. +2. Folosirea aplicatiei local: + - Pentru a folosi aplicatia local trebuie sa instalati [Docker](https://docs.docker.com/engine/install/),sa folositi comanda + `docker compose up` in folderul [infrastructure](./infrastructure) din proiect, sa create un nou fisier numit `.env` in + folderul [src](./src) si sa il completati cu datale din [compose.yml](./infrastructure/compose.yaml) + in modul prezentat in fisierul [.env.template](.env.template) +3. Rularea testelor: + - Pentru a rula testele trebuie sa adaugati unul dintre fisierele [env.bat](env.bat) sau [env.sh](env.sh) (primul pentru + Windows, al doilea pentru sisteme POSIX) in setarile toolchain-ului pe care il folositi (`File | Settings | Build, Execution, Deployment | Toolchains`) + la rubrica `Environment File`. Testele se ruleaza ori ruland executabilul `cmake-build-debug/tests/Password-Keeper-Test-Runner` ori ruland comanda ctest in folderul `cmake-build-debug`. + +## Pipeline +Pipeline-ul CI/CD este configurat în [GitHub Actions](./.github/workflows/cmake.yml) È™i include mai multe etape pentru a asigura calitatea codului, compatibilitatea È™i funcÈ›ionalitatea pe diferite platforme. + +Verificarea calității codului: +Primele două etape validează corectitudinea codului È™i se asigură că nu generează warnings ( folosind `Cppcheck` si `Clang-Tidy` ). + +Testarea compatibilității pe multiple sisteme de operare: +Următoarele cinci etape asigură rularea corectă a codului pe principalele sisteme de operare (Linux, macOS È™i Windows) È™i efectuează verificări de memorie folosind MSAN, ASAN È™i Valgrind, pentru a identifica posibile memory leaks È™i alte probleme legate de memorie. + +Rularea testelor funcÈ›ionale: +Ultima etapă rulează testele pentru a verifica dacă aplicaÈ›ia funcÈ›ionează conform aÈ™teptărilor. + +ÃŽn toate etapele care implică rularea aplicatiei este inclus un serviciu PostgreSQL pentru a permite rularea corectă a aplicaÈ›iei. ## Milestone #0 @@ -14,40 +75,47 @@ In acest moment proiectul poate fi construit numai folosind WSL. ## Milestone #1 #### CerinÈ›e + - [ ] definirea a minim **3-4 clase** folosind compunere cu clasele definite de voi - [ ] constructori de iniÈ›ializare cu parametri - [ ] pentru o aceeaÈ™i (singură) clasă: constructor de copiere, `operator=` de copiere, destructor - [ ] `operator<<` pentru toate clasele pentru afiÈ™are (std::ostream) - [ ] cât mai multe `const` (unde este cazul) -- [ ] implementarea a minim 3 funcÈ›ii membru publice pentru funcÈ›ionalități specifice temei alese, dintre care cel puÈ›in 1-2 funcÈ›ii mai complexe - - nu doar citiri/afișări sau adăugat/È™ters elemente într-un/dintr-un vector +- [ ] implementarea a minim 3 funcÈ›ii membru publice pentru funcÈ›ionalități specifice temei alese, dintre care cel puÈ›in + 1-2 funcÈ›ii mai complexe + - nu doar citiri/afișări sau adăugat/È™ters elemente într-un/dintr-un vector - [ ] scenariu de utilizare a claselor definite: - - preferabil sub formă de teste unitare, mai ales dacă vorbim de aplicaÈ›ii consolă - - crearea de obiecte È™i apelarea tuturor funcÈ›iilor membru publice în main - - vor fi adăugate în fiÈ™ierul `tastatura.txt` DOAR exemple de date de intrare de la tastatură (dacă există); dacă aveÈ›i nevoie de date din fiÈ™iere, creaÈ›i alte fiÈ™iere separat + - preferabil sub formă de teste unitare, mai ales dacă vorbim de aplicaÈ›ii consolă + - crearea de obiecte È™i apelarea tuturor funcÈ›iilor membru publice în main + - vor fi adăugate în fiÈ™ierul `tastatura.txt` DOAR exemple de date de intrare de la tastatură (dacă există); dacă + aveÈ›i nevoie de date din fiÈ™iere, creaÈ›i alte fiÈ™iere separat - [ ] tag de `git`: de exemplu `v0.1` - [ ] serviciu de integrare continuă (CI); exemplu: GitHub Actions ## Milestone #2 #### CerinÈ›e + - [ ] separarea codului din clase în `.h` (sau `.hpp`) È™i `.cpp` - [ ] moÈ™teniri: - - minim o clasă de bază È™i **3 clase derivate** din aceeaÈ™i ierarhie - - ierarhia trebuie să fie cu bază proprie, nu derivată dintr-o clasă predefinită - - [ ] funcÈ›ii virtuale (pure) apelate prin pointeri de bază din clasa care conÈ›ine atributul de tip pointer de bază - - minim o funcÈ›ie virtuală va fi **specifică temei** (e.g. nu simple citiri/afișări) - - constructori virtuali (clone): sunt necesari, dar nu se consideră funcÈ›ii specifice temei - - afiÈ™are virtuală, interfață non-virtuală - - [ ] apelarea constructorului din clasa de bază din constructori din derivate - - [ ] clasă cu atribut de tip pointer la o clasă de bază cu derivate; aici apelaÈ›i funcÈ›iile virtuale prin pointer de bază, eventual prin interfaÈ›a non-virtuală din bază - - [ ] suprascris cc/op= pentru copieri/atribuiri corecte, copy and swap - - [ ] `dynamic_cast`/`std::dynamic_pointer_cast` pentru downcast cu sens - - [ ] smart pointers (recomandat, opÈ›ional) + - minim o clasă de bază È™i **3 clase derivate** din aceeaÈ™i ierarhie + - ierarhia trebuie să fie cu bază proprie, nu derivată dintr-o clasă predefinită + - [ ] funcÈ›ii virtuale (pure) apelate prin pointeri de bază din clasa care conÈ›ine atributul de tip pointer de bază + - minim o funcÈ›ie virtuală va fi **specifică temei** (e.g. nu simple citiri/afișări) + - constructori virtuali (clone): sunt necesari, dar nu se consideră funcÈ›ii specifice temei + - afiÈ™are virtuală, interfață non-virtuală + - [ ] apelarea constructorului din clasa de bază din constructori din derivate + - [ ] clasă cu atribut de tip pointer la o clasă de bază cu derivate; aici apelaÈ›i funcÈ›iile virtuale prin pointer + de bază, eventual prin interfaÈ›a non-virtuală din bază + - [ ] suprascris cc/op= pentru copieri/atribuiri corecte, copy and swap + - [ ] `dynamic_cast`/`std::dynamic_pointer_cast` pentru downcast cu sens + - [ ] smart pointers (recomandat, opÈ›ional) - [ ] excepÈ›ii - - [ ] ierarhie proprie cu baza `std::exception` sau derivată din `std::exception`; minim **3** clase pentru erori specifice - - [ ] utilizare cu sens: de exemplu, `throw` în constructor (sau funcÈ›ie care întoarce un obiect), `try`/`catch` în `main` - - această ierarhie va fi complet independentă de ierarhia cu funcÈ›ii virtuale + - [ ] ierarhie proprie cu baza `std::exception` sau derivată din `std::exception`; minim **3** clase pentru erori + specifice + - [ ] utilizare cu sens: de exemplu, `throw` în constructor (sau funcÈ›ie care întoarce un obiect), `try`/`catch` în + `main` + - această ierarhie va fi complet independentă de ierarhia cu funcÈ›ii virtuale - [ ] funcÈ›ii È™i atribute `static` - [ ] STL - [ ] cât mai multe `const` @@ -57,10 +125,12 @@ In acest moment proiectul poate fi construit numai folosind WSL. ## Milestone #3 #### CerinÈ›e + - [ ] 2 È™abloane de proiectare (design patterns) - [ ] o clasă È™ablon cu sens; minim **2 instanÈ›ieri** - - [ ] preferabil È™i o funcÈ›ie È™ablon (template) cu sens; minim 2 instanÈ›ieri + - [ ] preferabil È™i o funcÈ›ie È™ablon (template) cu sens; minim 2 instanÈ›ieri - [ ] tag de `git`: de exemplu `v0.3` sau `v1.0` ## Resurse + - adăugaÈ›i trimiteri către resursele externe care v-au ajutat sau pe care le-aÈ›i folosit diff --git a/cmake/CompilerFlags.cmake b/cmake/CompilerFlags.cmake index d7d346e..a329bb5 100644 --- a/cmake/CompilerFlags.cmake +++ b/cmake/CompilerFlags.cmake @@ -1,27 +1,27 @@ # target definitions -if(GITHUB_ACTIONS) +if (GITHUB_ACTIONS) message("NOTE: GITHUB_ACTIONS defined") target_compile_definitions(${PROJECT_NAME} PRIVATE GITHUB_ACTIONS) -endif() +endif () ############################################################################### -if(PROJECT_WARNINGS_AS_ERRORS) +if (PROJECT_WARNINGS_AS_ERRORS) set_property(TARGET ${PROJECT_NAME} PROPERTY COMPILE_WARNING_AS_ERROR ON) -endif() +endif () # custom compiler flags message("Compiler: ${CMAKE_CXX_COMPILER_ID} version ${CMAKE_CXX_COMPILER_VERSION}") -if(MSVC) +if (MSVC) target_compile_options(${PROJECT_NAME} PRIVATE /W4 /permissive- /wd4244 /wd4267 /wd4996 /external:anglebrackets /external:W0 /utf-8 /MP) -else() - target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -pedantic) -endif() +else () + target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -pedantic -Wno-pre-c++2b-compat) +endif () ############################################################################### # sanitizers -include(cmake/CustomStdlibAndSanitizers.cmake) +include(${CMAKE_HELPER_DIR}/CustomStdlibAndSanitizers.cmake) set_custom_stdlib_and_sanitizers(${PROJECT_NAME} true) diff --git a/cmake/CopyHelper.cmake b/cmake/CopyHelper.cmake index 2ef52b8..baf8224 100644 --- a/cmake/CopyHelper.cmake +++ b/cmake/CopyHelper.cmake @@ -6,26 +6,26 @@ function(copy_files) cmake_parse_arguments(PARSE_ARGV 0 ARG "${options}" "${oneValueArgs}" "${multiValueArgs}") # copy files to build dir - foreach(file ${ARG_FILES}) + foreach (file ${ARG_FILES}) add_custom_command( - TARGET ${PROJECT_NAME} POST_BUILD - COMMENT "Copying ${file}..." - COMMAND ${CMAKE_COMMAND} -E copy_if_different - ${CMAKE_SOURCE_DIR}/${file} $) - # ${CMAKE_CURRENT_BINARY_DIR}) - endforeach() + TARGET ${PROJECT_NAME} POST_BUILD + COMMENT "Copying ${file}..." + COMMAND ${CMAKE_COMMAND} -E copy_if_different + ${PROJECT_ROOT}/${file} $) + # ${CMAKE_CURRENT_BINARY_DIR}) + endforeach () # copy folders to build dir - foreach(dir ${ARG_DIRECTORY}) + foreach (dir ${ARG_DIRECTORY}) add_custom_command( - TARGET ${PROJECT_NAME} POST_BUILD - COMMENT "Copying directory ${dir}..." - COMMAND ${CMAKE_COMMAND} -E copy_directory_if_different - ${CMAKE_SOURCE_DIR}/${dir} $/${dir}) - # ${CMAKE_CURRENT_BINARY_DIR}/${dir}) - endforeach() + TARGET ${PROJECT_NAME} POST_BUILD + COMMENT "Copying directory ${dir}..." + COMMAND ${CMAKE_COMMAND} -E copy_directory_if_different + ${PROJECT_ROOT}/${dir} $/${dir}) + # ${CMAKE_CURRENT_BINARY_DIR}/${dir}) + endforeach () # copy files and folders to install dir - install(FILES ${ARG_FILES} DESTINATION ${DESTINATION_DIR}) - install(DIRECTORY ${ARG_DIRECTORY} DESTINATION ${DESTINATION_DIR}) + install(FILES ${PROJECT_ROOT/ARG_FILES} DESTINATION ${DESTINATION_DIR}) + install(DIRECTORY ${PROJECT_ROOT/ARG_DIRECTORY} DESTINATION ${DESTINATION_DIR}) endfunction() diff --git a/cmake/CustomStdlibAndSanitizers.cmake b/cmake/CustomStdlibAndSanitizers.cmake index 5e8f26e..ba5a2a9 100644 --- a/cmake/CustomStdlibAndSanitizers.cmake +++ b/cmake/CustomStdlibAndSanitizers.cmake @@ -1,48 +1,48 @@ include(${CMAKE_CURRENT_LIST_DIR}/DetectLibcpp.cmake) function(set_custom_stdlib_and_sanitizers target add_apple_asan) - if(MSVC) + if (MSVC) # see https://gitlab.kitware.com/cmake/cmake/-/issues/24922 set_target_properties(${target} PROPERTIES VS_USER_PROPS "${CMAKE_SOURCE_DIR}/disable_modules.props") target_compile_options(${target} PRIVATE /experimental:module-) - if(USE_ASAN) + if (USE_ASAN) target_compile_options(${target} PRIVATE "$<${debug_mode}:/fsanitize=address>") - endif() + endif () return() - endif() + endif () - if("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" AND NOT WIN32) + if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" AND NOT WIN32) detect_libcpp() - if(HAS_LIBCPP) + if (HAS_LIBCPP) # see also https://stackoverflow.com/a/70382484 target_compile_options(${target} PRIVATE -stdlib=libc++) target_link_options(${target} PRIVATE -stdlib=libc++) - else() + else () # fall back to libstdc++ target_compile_options(${target} PRIVATE -stdlib=libstdc++) target_link_options(${target} PRIVATE -stdlib=libstdc++) - endif() - endif() + endif () + endif () - if(APPLE) + if (APPLE) # first check Apple since Apple is also a kind of Unix - if("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" AND add_apple_asan MATCHES true) - if(USE_ASAN) + if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" AND add_apple_asan MATCHES true) + if (USE_ASAN) target_compile_options(${target} PRIVATE "$<${debug_mode}:-fsanitize=address,undefined>") target_link_options(${target} PRIVATE "$<${debug_mode}:-fsanitize=address,undefined>") - endif() - endif() - elseif(UNIX) - if(USE_ASAN) + endif () + endif () + elseif (UNIX) + if (USE_ASAN) # check leaks on Linux since macOS does not support the leaks sanitizer yet # leaks sanitizer is enabled by default on Linux, so we do not need to enable it explicitly target_compile_options(${target} PRIVATE "$<${debug_mode}:-fsanitize=address,undefined>") target_link_options(${target} PRIVATE "$<${debug_mode}:-fsanitize=address,undefined>") - elseif(USE_MSAN) + elseif (USE_MSAN) # use semi-colons instead of spaces to separate arguments # it is recommended to quote generator expressions in order to avoid unintentional splitting target_compile_options(${target} PRIVATE "$<${debug_mode}:-fsanitize=memory,undefined;-fsanitize-recover=memory,undefined;-fsanitize-memory-track-origins>") target_link_options(${target} PRIVATE "$<${debug_mode}:-fsanitize=memory,undefined;-fsanitize-recover=memory,undefined;-fsanitize-memory-track-origins;-Wl,-rpath,tools/llvm-project/build/lib>") - endif() - endif() + endif () + endif () endfunction() diff --git a/cmake/Options.cmake b/cmake/Options.cmake index b6e29a1..70215f3 100644 --- a/cmake/Options.cmake +++ b/cmake/Options.cmake @@ -2,13 +2,15 @@ option(WARNINGS_AS_ERRORS "Treat warnings as errors" OFF) option(USE_ASAN "Use Address Sanitizer" OFF) option(USE_MSAN "Use Memory Sanitizer" OFF) option(CMAKE_COLOR_DIAGNOSTICS "Enable color diagnostics" ON) +option(RUN_TESTS "Run the test suites" OFF) + # update name in .github/workflows/cmake.yml:27 when changing "bin" name here set(DESTINATION_DIR "bin") -if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) +if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) set(CMAKE_INSTALL_PREFIX "${PROJECT_SOURCE_DIR}/install_dir" CACHE PATH "..." FORCE) -endif() +endif () # disable sanitizers when releasing executables without explicitly requested debug info # use generator expressions to set flags correctly in both single and multi config generators diff --git a/ext/include/digestpp/LICENSE b/ext/include/digestpp/LICENSE new file mode 100644 index 0000000..fdddb29 --- /dev/null +++ b/ext/include/digestpp/LICENSE @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to diff --git a/ext/include/digestpp/algorithm/blake.hpp b/ext/include/digestpp/algorithm/blake.hpp new file mode 100644 index 0000000..74c7ce3 --- /dev/null +++ b/ext/include/digestpp/algorithm/blake.hpp @@ -0,0 +1,47 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_ALGORITHM_BLAKE_HPP +#define DIGESTPP_ALGORITHM_BLAKE_HPP + +#include "../hasher.hpp" +#include "detail/blake_provider.hpp" +#include "mixin/blake_mixin.hpp" + +namespace digestpp +{ + +/** + * @brief BLAKE hash function (SHA-3 finalist) + * + * @hash + * + * @outputsize 224 / 256 / 384 / 512 bits + * + * @defaultsize none + * + * @throw std::runtime_error if the requested digest size is not supported + * + * @mixinparams salt + * + * @mixin{mixin::blake_mixin} + * + * @par Example:\n + * @code // Output a 256-bit BLAKE digest of a string + * digestpp::blake hasher(256); + * hasher.absorb("The quick brown fox jumps over the lazy dog"); + * std::cout << hasher.hexdigest() << '\n'; + * @endcode + * + * @par Example output:\n + * @code 7576698ee9cad30173080678e5965916adbb11cb5245d386bf1ffda1cb26c9d7 + * @endcode + * + * @sa hasher, mixin::blake_mixin + */ +typedef hasher blake; + +} // namespace digestpp + +#endif // DIGESTPP_ALGORITHM_BLAKE_HPP \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/blake2.hpp b/ext/include/digestpp/algorithm/blake2.hpp new file mode 100644 index 0000000..2639800 --- /dev/null +++ b/ext/include/digestpp/algorithm/blake2.hpp @@ -0,0 +1,196 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_ALGORITHM_BLAKE2_HPP +#define DIGESTPP_ALGORITHM_BLAKE2_HPP + +#include "../hasher.hpp" +#include "detail/blake2_provider.hpp" +#include "mixin/blake2_mixin.hpp" + +/// digestpp namespace +namespace digestpp +{ + +/** + * @brief BLAKE2b hash function + * + * @hash + * + * @outputsize 8 - 512 bits + * + * @defaultsize 512 bits + * + * @throw std::runtime_error if the requested digest size is not divisible by 8 (full bytes), + * or is not within the supported range + * + * @mixinparams salt, personalization, key + * + * @mixin{mixin::blake2_mixin} + * + * @par Example:\n + * @code // Output a 256-bit BLAKE2b digest of a string + * digestpp::blake2b hasher(256); + * hasher.absorb("The quick brown fox jumps over the lazy dog"); + * std::cout << hasher.hexdigest() << '\n'; + * @endcode + * + * @par Example output:\n + * @code 01718cec35cd3d796dd00020e0bfecb473ad23457d063b75eff29c0ffa2e58a9 + * @endcode + * + * @sa hasher, mixin::blake2_mixin + */ +typedef hasher, mixin::blake2_mixin> blake2b; + +/** + * @brief BLAKE2s hash function + * + * @hash + * + * @outputsize 8 - 256 bits + * + * @defaultsize 256 bits + * + * @throw std::runtime_error if the requested digest size is not divisible by 8 (full bytes), + * or is not within the supported range + * + * @mixinparams salt, personalization, key + * + * @mixin{mixin::blake2_mixin} + * + * @par Example:\n + * @code // Output a 256-bit BLAKE2s digest of a string + * digestpp::blake2s hasher; + * hasher.absorb("The quick brown fox jumps over the lazy dog"); + * std::cout << hasher.hexdigest() << '\n'; + * @endcode + * + * @par Example output:\n + * @code 606beeec743ccbeff6cbcdf5d5302aa855c256c29b88c8ed331ea1a6bf3c8812 + * @endcode + * + * @sa hasher, mixin::blake2_mixin + */ +typedef hasher, mixin::blake2_mixin> blake2s; + +/** + * @brief BLAKE2xb hash function + * + * Use this variant when the required hash size is known in advance. Otherwise, use \ref blake2xb_xof + * + * @hash + * + * @outputsize arbitrary + * + * @defaultsize 512 bits + * + * @throw std::runtime_error if the requested digest size is not divisible by 8 (full bytes) + * + * @mixinparams salt, personalization, key + * + * @mixin{mixin::blake2_mixin} + * + * @par Example:\n + * @code // Output a 256-bit BLAKE2xb digest of a string + * digestpp::blake2xb hasher(256); + * hasher.absorb("The quick brown fox jumps over the lazy dog"); + * std::cout << hasher.hexdigest() << '\n'; + * @endcode + * + * @par Example output:\n + * @code ca7a0c9c54b4b93c0bee0aa3a4d63e4f7fb87e3e0a9050522377fde76f0b6c01 + * @endcode + * + * @sa hasher, mixin::blake2_mixin + */ +typedef hasher, mixin::blake2_mixin> blake2xb; + +/** + * @brief BLAKE2xs hash function + * + * Use this variant when the required hash size is known in advance. Otherwise, use \ref blake2xs_xof + * + * @hash + * + * @outputsize arbitrary + * + * @defaultsize 256 bits + * + * @throw std::runtime_error if the requested digest size is not divisible by 8 (full bytes) + * + * @mixinparams salt, personalization, key + * + * @mixin{mixin::blake2_mixin} + * + * @par Example:\n + * @code // Output a 512-bit BLAKE2xs digest of a string + * digestpp::blake2xs hasher(512); + * hasher.absorb("The quick brown fox jumps over the lazy dog"); + * std::cout << hasher.hexdigest() << '\n'; + * @endcode + * + * @par Example output:\n + * @code e709f8377d21507c166e5dd2279a1f58b290792d65dafcc5647b6e439a974227503c341341572725709b874e95f13a438677aa6f9648467fd341e0f3e5421840 + * @endcode + * + * @sa hasher, mixin::blake2_mixin + */ +typedef hasher, mixin::blake2_mixin> blake2xs; + +/** + * @brief BLAKE2xb in XOF mode + * + * Use this variant when the required hash size is not known in advance. Otherwise, use \ref blake2xb + * + * @xof + * + * @mixinparams salt, personalization, key + * + * @mixin{mixin::blake2_mixin} + * + * @par Example:\n + * @code // Absorb a string and squeeze 32 bytes of output + * digestpp::blake2xb_xof hasher; + * hasher.absorb("The quick brown fox jumps over the lazy dog"); + * std::cout << hasher.hexsqueeze(32) << '\n'; + * @endcode + * + * @par Example output:\n + * @code 364e84ca4c103df292306c93ebba6f6633d5e9cc8a95e040498e9a012d5ca534 + * @endcode + * + * @sa hasher, mixin::blake2_mixin + */ +typedef hasher, mixin::blake2_mixin> blake2xb_xof; + +/** + * @brief BLAKE2xs in XOF mode + * + * Use this variant when the required hash size is not known in advance. Otherwise, use \ref blake2xs + * + * @xof + * + * @mixinparams salt, personalization, key + * + * @mixin{mixin::blake2_mixin} + * + * @par Example:\n + * @code // Absorb a string and squeeze 32 bytes of output + * digestpp::blake2xs_xof hasher; + * hasher.absorb("The quick brown fox jumps over the lazy dog"); + * std::cout << hasher.hexsqueeze(32) << '\n'; + * @endcode + * + * @par Example output:\n + * @code 0650cde4df888a06eada0f0fecb3c17594304b4a03fdd678182f27db1238b1747e33c34ae539fe2179a7594442b5cc9a7a0f398bb15ac3095a397de6a60061d6 + * @endcode + * + * @sa hasher, mixin::blake2_mixin + */ +typedef hasher, mixin::blake2_mixin> blake2xs_xof; + +} // namespace digestpp + +#endif // DIGESTPP_ALGORITHM_BLAKE2_HPP \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/detail/blake2_provider.hpp b/ext/include/digestpp/algorithm/detail/blake2_provider.hpp new file mode 100644 index 0000000..44a2f40 --- /dev/null +++ b/ext/include/digestpp/algorithm/detail/blake2_provider.hpp @@ -0,0 +1,342 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_PROVIDERS_BLAKE2_HPP +#define DIGESTPP_PROVIDERS_BLAKE2_HPP + +#include "../../detail/functions.hpp" +#include "../../detail/absorb_data.hpp" +#include "../../detail/validate_hash_size.hpp" +#include "constants/blake2_constants.hpp" +#include +#include + +namespace digestpp +{ + +namespace detail +{ + +namespace blake2_functions +{ + static inline void G(int r, int i, uint64_t& a, uint64_t& b, uint64_t& c, uint64_t& d, uint64_t* M) + { + a = a + b + M[blake2_constants::S[r][2 * i]]; + d = rotate_right(d ^ a, 32); + c = c + d; + b = rotate_right(b ^ c, 24); + a = a + b + M[blake2_constants::S[r][2 * i + 1]]; + d = rotate_right(d ^ a, 16); + c = c + d; + b = rotate_right(b ^ c, 63); + } + + static inline void G(int r, int i, uint32_t& a, uint32_t& b, uint32_t& c, uint32_t& d, uint32_t* M) + { + a = a + b + M[blake2_constants::S[r][2 * i]]; + d = rotate_right(d ^ a, 16); + c = c + d; + b = rotate_right(b ^ c, 12); + a = a + b + M[blake2_constants::S[r][2 * i + 1]]; + d = rotate_right(d ^ a, 8); + c = c + d; + b = rotate_right(b ^ c, 7); + } + + template + static inline void round(int r, T* M, T* v) + { + G(r, 0, v[0], v[4], v[8], v[12], M); + G(r, 1, v[1], v[5], v[9], v[13], M); + G(r, 2, v[2], v[6], v[10], v[14], M); + G(r, 3, v[3], v[7], v[11], v[15], M); + G(r, 4, v[0], v[5], v[10], v[15], M); + G(r, 5, v[1], v[6], v[11], v[12], M); + G(r, 6, v[2], v[7], v[8], v[13], M); + G(r, 7, v[3], v[4], v[9], v[14], M); + } + + template + inline T IV(int t); + + template<> + inline uint32_t IV(int t) + { + return blake2s_constants::IV[t]; + } + + template<> + inline uint64_t IV(int t) + { + return blake2b_constants::IV[t]; + } + + inline void initH(std::array& H) + { + memcpy(&H[0], blake2s_constants::IV, 32); + H[0] ^= 0x01010000ULL; + } + + inline void initH(std::array& H) + { + memcpy(&H[0], blake2b_constants::IV, 64); + H[0] ^= 0x0000000001010000ULL; + } + + inline void initX(std::array& H, size_t hs, size_t processed, size_t xoffset, uint32_t rhs) + { + memcpy(&H[0], blake2s_constants::IV, 32); + H[0] ^= (rhs == std::numeric_limits::max() ? static_cast(32) : std::min(hs - processed, static_cast(32))); + H[1] ^= 0x00000020; + H[2] ^= xoffset; + H[3] ^= 0x20000000; + H[3] ^= static_cast(rhs); + } + + inline void initX(std::array& H, size_t hs, size_t processed, size_t xoffset, uint64_t rhs) + { + memcpy(&H[0], blake2b_constants::IV, 64); + H[0] ^= (rhs == std::numeric_limits::max() ? static_cast(64) : std::min(hs - processed, static_cast(64))); + H[0] ^= 0x0000004000000000ULL; + H[1] ^= xoffset; + H[1] ^= rhs << 32; + H[2] ^= 0x0000000000004000ULL; + } + +} + +template +class blake2_provider +{ +public: + static const bool is_xof = type == blake2_type::xof; + + blake2_provider(size_t hashsize = N) + : hs(hashsize), squeezing(false) + { + static_assert(sizeof(T) == 8 || sizeof(T) == 4, "Invalid T size"); + + if (type == blake2_type::hash) + detail::validate_hash_size(hashsize, N); + else if (type == blake2_type::x_hash) + detail::validate_hash_size(hashsize, N * sizeof(T) * 4 - 16); + + zero_memory(s); + zero_memory(p); + } + + ~blake2_provider() + { + clear(); + } + + inline void init() + { + pos = 0; + total = 0; + xoffset = 0; + squeezing = false; + + blake2_functions::initH(H); + + if (type == blake2_type::hash) + H[0] ^= hash_size()/8; + else + { + H[0] ^= N / 8; + T rhs = type == blake2_type::x_hash ? static_cast(hs/8) : (static_cast(-1) >> (sizeof(T) * 4)); + if (N == 512) + H[1] ^= (rhs << (N / 16)); + else + H[3] ^= rhs; + } + H[0] ^= (k.size() << 8); + H[4] ^= s[0]; + H[5] ^= s[1]; + H[6] ^= p[0]; + H[7] ^= p[1]; + absorb_key(); + } + + inline void update(const unsigned char* data, size_t len) + { + detail::absorb_bytes(data, len, N / 4, N / 4 + 1, m.data(), pos, total, + [this](const unsigned char* data, size_t len) { transform(data, len, false); }); + } + + inline void set_key(const std::string& key) + { + if (key.length() > N / 8) + throw std::runtime_error("invalid key length"); + + k = key; + } + + inline void set_salt(const unsigned char* salt, size_t salt_len) + { + if (salt_len && salt_len != N / 32) + throw std::runtime_error("invalid salt length"); + + memcpy(&s[0], salt, salt_len); + } + + inline void set_personalization(const unsigned char* personalization, size_t personalization_len) + { + if (personalization_len && personalization_len != N / 32) + throw std::runtime_error("invalid personalization length"); + + memcpy(&p[0], personalization, personalization_len); + } + + inline void squeeze(unsigned char* hash, size_t hs) + { + size_t processed = 0; + if (!squeezing) + { + if (type == blake2_type::xof) + total += pos * 8; + squeezing = true; + xoffset = 0; + if (N / 4 != pos) + memset(&m[pos], 0, N / 4 - pos); + transform(m.data(), 1, true); + memcpy(&m[0], H.data(), N / 8); + } + else if (pos < N / 8) + { + size_t to_copy = std::min(hs, N / 8 - pos); + memcpy(hash, reinterpret_cast(H.data()) + pos, to_copy); + processed += to_copy; + pos += to_copy; + } + while (processed < hs) + { + blake2_functions::initX(H, hs, processed, xoffset++, type == blake2_type::xof ? static_cast(-1) : static_cast(hs)); + H[4] ^= s[0]; + H[5] ^= s[1]; + H[6] ^= p[0]; + H[7] ^= p[1]; + total = N; + memset(&m[N / 8], 0, m.size() - N / 8); + transform(m.data(), 1, true); + pos = std::min(hs - processed, N / 8); + memcpy(hash + processed, H.data(), pos); + processed += pos; + } + } + + inline void final(unsigned char* hash) + { + total += pos * 8; + if (type == blake2_type::hash) + { + if (N / 4 != pos) + memset(&m[pos], 0, N / 4 - pos); + transform(m.data(), 1, true); + memcpy(hash, H.data(), hash_size() / 8); + } + else + squeeze(hash, hs / 8); + } + + inline void clear() + { + zero_memory(H); + zero_memory(m); + zero_memory(s); + zero_memory(p); + zero_memory(k); + k.clear(); + } + + inline size_t hash_size() const { return hs; } + +private: + inline void absorb_key() + { + if (k.empty()) + return; + + unsigned char key[N / 4]; + memcpy(key, k.data(), k.length()); + if (k.length() != N / 4) + memset(key + k.length(), 0, N / 4 - k.length()); + update(key, sizeof(key)); + } + + inline void transform(const unsigned char* data, size_t num_blks, bool padding) + { + for (size_t blk = 0; blk < num_blks; blk++) + { + T M[16]; + for (int i = 0; i < 16; i++) + M[i] = reinterpret_cast(data)[blk * 16 + i]; + uint64_t totalbytes = total / 8 + (padding ? 0 : (blk + 1) * N) / 4; + T t0 = static_cast(totalbytes); + T t1 = N == 512 ? 0 : static_cast(totalbytes >> 32); + T f0 = 0; + T f1 = 0; + if (padding) + { + f0 = static_cast(-1); + f1 = 0; + } + + T v[16]; + memcpy(v, H.data(), sizeof(T) * 8); + v[8 + 0] = blake2_functions::IV(0); + v[8 + 1] = blake2_functions::IV(1); + v[8 + 2] = blake2_functions::IV(2); + v[8 + 3] = blake2_functions::IV(3); + v[12] = t0 ^ blake2_functions::IV(4); + v[13] = t1 ^ blake2_functions::IV(5); + v[14] = f0 ^ blake2_functions::IV(6); + v[15] = f1 ^ blake2_functions::IV(7); + + blake2_functions::round(0, M, v); + blake2_functions::round(1, M, v); + blake2_functions::round(2, M, v); + blake2_functions::round(3, M, v); + blake2_functions::round(4, M, v); + blake2_functions::round(5, M, v); + blake2_functions::round(6, M, v); + blake2_functions::round(7, M, v); + blake2_functions::round(8, M, v); + blake2_functions::round(9, M, v); + if (N == 512) + { + blake2_functions::round(10, M, v); + blake2_functions::round(11, M, v); + } + + H[0] = H[0] ^ v[0] ^ v[0 + 8]; + H[0 + 4] = H[0 + 4] ^ v[0 + 4] ^ v[0 + 8 + 4]; + H[1] = H[1] ^ v[1] ^ v[1 + 8]; + H[1 + 4] = H[1 + 4] ^ v[1 + 4] ^ v[1 + 8 + 4]; + H[2] = H[2] ^ v[2] ^ v[2 + 8]; + H[2 + 4] = H[2 + 4] ^ v[2 + 4] ^ v[2 + 8 + 4]; + H[3] = H[3] ^ v[3] ^ v[3 + 8]; + H[3 + 4] = H[3 + 4] ^ v[3 + 4] ^ v[3 + 8 + 4]; + } + + } + + constexpr static size_t N = sizeof(T) == 8 ? 512 : 256; + std::array H; + std::array s; + std::array p; + std::string k; + std::array m; + size_t pos; + uint64_t total; + size_t hs; + size_t xoffset; + bool squeezing; +}; + +} // namespace detail + +} // namespace digestpp + +#endif diff --git a/ext/include/digestpp/algorithm/detail/blake_provider.hpp b/ext/include/digestpp/algorithm/detail/blake_provider.hpp new file mode 100644 index 0000000..e2839a2 --- /dev/null +++ b/ext/include/digestpp/algorithm/detail/blake_provider.hpp @@ -0,0 +1,301 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_PROVIDERS_BLAKE_HPP +#define DIGESTPP_PROVIDERS_BLAKE_HPP + +#include "../../detail/functions.hpp" +#include "../../detail/absorb_data.hpp" +#include "../../detail/validate_hash_size.hpp" +#include "constants/blake_constants.hpp" +#include + +namespace digestpp +{ + +namespace detail +{ + +namespace blake_functions +{ + static inline void G(int r, int i, uint32_t& a, uint32_t& b, uint32_t& c, uint32_t& d, uint32_t* M) + { + a = a + b + (M[blake_constants::S[r % 10][2 * i]] + ^ blake_constants::c[blake_constants::S[r % 10][2 * i + 1]]); + d = rotate_right(d ^ a, 16); + c = c + d; + b = rotate_right(b ^ c, 12); + a = a + b + (M[blake_constants::S[r % 10][2 * i + 1]] + ^ blake_constants::c[blake_constants::S[r % 10][2 * i]]); + d = rotate_right(d ^ a, 8); + c = c + d; + b = rotate_right(b ^ c, 7); + } + + static inline void G(int r, int i, uint64_t& a, uint64_t& b, uint64_t& c, uint64_t& d, uint64_t* M) + { + a = a + b + (M[blake_constants::S[r % 10][2 * i]] + ^ blake_constants::c512[blake_constants::S[r % 10][2 * i + 1]]); + d = rotate_right(d ^ a, 32); + c = c + d; + b = rotate_right(b ^ c, 25); + a = a + b + (M[blake_constants::S[r % 10][2 * i + 1]] + ^ blake_constants::c512[blake_constants::S[r % 10][2 * i]]); + d = rotate_right(d ^ a, 16); + c = c + d; + b = rotate_right(b ^ c, 11); + } + + template + static inline void round(int r, T* M, T* v) + { + G(r, 0, v[0], v[4], v[8], v[12], M); + G(r, 1, v[1], v[5], v[9], v[13], M); + G(r, 2, v[2], v[6], v[10], v[14], M); + G(r, 3, v[3], v[7], v[11], v[15], M); + G(r, 4, v[0], v[5], v[10], v[15], M); + G(r, 5, v[1], v[6], v[11], v[12], M); + G(r, 6, v[2], v[7], v[8], v[13], M); + G(r, 7, v[3], v[4], v[9], v[14], M); + } + + template + inline T C(int t); + + template<> + inline uint32_t C(int t) + { + return blake_constants::c[t]; + } + + template<> + inline uint64_t C(int t) + { + return blake_constants::c512[t]; + } + + template + inline void transform(const unsigned char* data, size_t num_blks, bool padding, std::array& H, uint64_t total, bool final) + { + for (size_t blk = 0; blk < num_blks; blk++) + { + T M[16]; + for (int i = 0; i < 16; i++) + M[i] = byteswap(reinterpret_cast(data)[blk * 16 + i]); + + uint64_t totalbytes = total + (!final ? (blk + 1) * sizeof(M) * 8 : 0); + T t0 = static_cast(totalbytes); + T t1 = sizeof(T) == 8 ? 0 : static_cast(totalbytes >> 32); + if (padding) + t0 = t1 = 0; + + T v[16]; + memcpy(v, H.data(), sizeof(T) * 8); + v[8 + 0] = H[8] ^ C(0); + v[8 + 1] = H[9] ^ C(1); + v[8 + 2] = H[10] ^ C(2); + v[8 + 3] = H[11] ^ C(3); + v[12] = t0 ^ C(4); + v[13] = t0 ^ C(5); + v[14] = t1 ^ C(6); + v[15] = t1 ^ C(7); + + // The loop is fully unrolled for performance reasons + round(0, M, v); + round(1, M, v); + round(2, M, v); + round(3, M, v); + round(4, M, v); + round(5, M, v); + round(6, M, v); + round(7, M, v); + round(8, M, v); + round(9, M, v); + round(10, M, v); + round(11, M, v); + round(12, M, v); + round(13, M, v); + if (sizeof(T) == 8) + { + round(14, M, v); + round(15, M, v); + } + + H[0] = H[0] ^ H[8] ^ v[0] ^ v[0 + 8]; + H[0 + 4] = H[0 + 4] ^ H[8] ^ v[0 + 4] ^ v[0 + 8 + 4]; + H[1] = H[1] ^ H[9] ^ v[1] ^ v[1 + 8]; + H[1 + 4] = H[1 + 4] ^ H[9] ^ v[1 + 4] ^ v[1 + 8 + 4]; + H[2] = H[2] ^ H[10] ^ v[2] ^ v[2 + 8]; + H[2 + 4] = H[2 + 4] ^ H[10] ^ v[2 + 4] ^ v[2 + 8 + 4]; + H[3] = H[3] ^ H[11] ^ v[3] ^ v[3 + 8]; + H[3 + 4] = H[3 + 4] ^ H[11] ^ v[3 + 4] ^ v[3 + 8 + 4]; + } + } + + template + inline void set_salt(std::array& H, const unsigned char* salt, size_t saltlen) + { + if (saltlen) + for (int i = 0; i < 4; i++) + H[8 + i] = byteswap(reinterpret_cast(salt)[i]); + else + H[8] = H[9] = H[10] = H[11] = 0; + } +} + +class blake_provider +{ +public: + static const bool is_xof = false; + + blake_provider(size_t hashsize) + : hs(hashsize) + { + validate_hash_size(hashsize, {224, 256, 384, 512}); + zero_memory(u.H512); + } + + ~blake_provider() + { + clear(); + } + + inline void init() + { + pos = 0; + total = 0; + + switch(hs) + { + case 512: + u.H512[0] = 0x6A09E667F3BCC908ull; + u.H512[1] = 0xBB67AE8584CAA73Bull; + u.H512[2] = 0x3C6EF372FE94F82Bull; + u.H512[3] = 0xA54FF53A5F1D36F1ull; + u.H512[4] = 0x510E527FADE682D1ull; + u.H512[5] = 0x9B05688C2B3E6C1Full; + u.H512[6] = 0x1F83D9ABFB41BD6Bull; + u.H512[7] = 0x5BE0CD19137E2179ull; + break; + case 384: + u.H512[0] = 0xcbbb9d5dc1059ed8ull; + u.H512[1] = 0x629a292a367cd507ull; + u.H512[2] = 0x9159015a3070dd17ull; + u.H512[3] = 0x152fecd8f70e5939ull; + u.H512[4] = 0x67332667ffc00b31ull; + u.H512[5] = 0x8eb44a8768581511ull; + u.H512[6] = 0xdb0c2e0d64f98fa7ull; + u.H512[7] = 0x47b5481dbefa4fa4ull; + break; + case 256: + u.H256[0] = 0x6a09e667; + u.H256[1] = 0xbb67ae85; + u.H256[2] = 0x3c6ef372; + u.H256[3] = 0xa54ff53a; + u.H256[4] = 0x510e527f; + u.H256[5] = 0x9b05688c; + u.H256[6] = 0x1f83d9ab; + u.H256[7] = 0x5be0cd19; + break; + case 224: + u.H256[0] = 0xC1059ED8; + u.H256[1] = 0x367CD507; + u.H256[2] = 0x3070DD17; + u.H256[3] = 0xF70E5939; + u.H256[4] = 0xFFC00B31; + u.H256[5] = 0x68581511; + u.H256[6] = 0x64F98FA7; + u.H256[7] = 0xBEFA4FA4; + break; + } + } + + inline void update(const unsigned char* data, size_t len) + { + detail::absorb_bytes(data, len, block_bytes(), block_bytes(), m.data(), pos, total, + [this](const unsigned char* data, size_t len) { transform(data, len, false, false); }); + } + + inline void set_salt(const unsigned char* salt, size_t salt_len) + { + if (salt_len && ((hs > 256 && salt_len != 32) || (hs <= 256 && salt_len != 16))) + throw std::runtime_error("invalid salt length"); + + if (hs > 256) + blake_functions::set_salt(u.H512, salt, salt_len); + else + blake_functions::set_salt(u.H256, salt, salt_len); + } + + inline void final(unsigned char* hash) + { + size_t messageend = hs > 256 ? 111 : 55; + bool truncated = hs != 512 && hs != 256; + bool padding = !pos; + total += 8 * pos; + m[pos] = pos == messageend && !truncated ? 0x81 : 0x80; + if (pos++ > messageend) + { + if (block_bytes() != pos) + memset(&m[pos], 0, block_bytes() - pos); + transform(m.data(), 1, false, true); + pos = 0; + padding = true; + } + if (pos <= messageend) + { + memset(&m[pos], 0, messageend - pos); + m[messageend] = truncated ? 0x00 : 0x01; + } + uint64_t mlen = byteswap(total); + if (block_bytes() == 128) + memset(&m[128 - 16], 0, sizeof(uint64_t)); + memcpy(&m[block_bytes() - 8], &mlen, sizeof(uint64_t)); + transform(m.data(), 1, padding, true); + if (hs > 256) + { + for (int i = 0; i < 8; i++) + u.H512[i] = byteswap(u.H512[i]); + memcpy(hash, u.H512.data(), hash_size()/8); + } + else + { + for (int i = 0; i < 8; i++) + u.H256[i] = byteswap(u.H256[i]); + memcpy(hash, u.H256.data(), hash_size()/8); + } + } + + inline void clear() + { + zero_memory(u.H512); + zero_memory(m); + } + + inline size_t hash_size() const { return hs; } + +private: + inline size_t block_bytes() const { return hs > 256 ? 128 : 64; } + + inline void transform(const unsigned char* mp, size_t num_blks, bool padding, bool final) + { + if (hs > 256) + blake_functions::transform(mp, num_blks, padding, u.H512, total, final); + else + blake_functions::transform(mp, num_blks, padding, u.H256, total, final); + } + + union { std::array H512; std::array H256; } u; + std::array m; + size_t hs; + size_t pos; + uint64_t total; + +}; + +} // namespace detail + +} // namespace digestpp + +#endif \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/detail/constants/blake2_constants.hpp b/ext/include/digestpp/algorithm/detail/constants/blake2_constants.hpp new file mode 100644 index 0000000..955ff9b --- /dev/null +++ b/ext/include/digestpp/algorithm/detail/constants/blake2_constants.hpp @@ -0,0 +1,71 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_PROVIDERS_BLAKE2_CONSTANTS_HPP +#define DIGESTPP_PROVIDERS_BLAKE2_CONSTANTS_HPP + +namespace digestpp +{ + +namespace detail +{ + +template +struct blake2b_constants +{ + const static uint64_t IV[8]; +}; + +template +const uint64_t blake2b_constants::IV[8] = { + 0x6A09E667F3BCC908ull, 0xBB67AE8584CAA73Bull, 0x3C6EF372FE94F82Bull, 0xA54FF53A5F1D36F1ull, + 0x510E527FADE682D1ull, 0x9B05688C2B3E6C1Full, 0x1F83D9ABFB41BD6Bull, 0x5BE0CD19137E2179ull +}; + +template +struct blake2s_constants +{ + const static uint32_t IV[8]; +}; + +template +const uint32_t blake2s_constants::IV[8] = { + 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 +}; + +template +struct blake2_constants +{ + static const uint32_t S[12][16]; + +}; + +template +const uint32_t blake2_constants::S[12][16] = { + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, + { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }, + { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 }, + { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 }, + { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 }, + { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 }, + { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 }, + { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 }, + { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 }, + { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 }, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, + { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } +}; + +enum class blake2_type +{ + hash, + x_hash, + xof +}; + +} // namespace detail + +} // namespace digestpp + +#endif \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/detail/constants/blake_constants.hpp b/ext/include/digestpp/algorithm/detail/constants/blake_constants.hpp new file mode 100644 index 0000000..090c261 --- /dev/null +++ b/ext/include/digestpp/algorithm/detail/constants/blake_constants.hpp @@ -0,0 +1,55 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_PROVIDERS_BLAKE_CONSTANTS_HPP +#define DIGESTPP_PROVIDERS_BLAKE_CONSTANTS_HPP + +namespace digestpp +{ + +namespace detail +{ + +template +struct blake_constants +{ + static const uint32_t c[16]; + static const uint64_t c512[16]; + static const uint32_t S[10][16]; + +}; + +template +const uint32_t blake_constants::c[16] = { + 0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344, 0xA4093822, 0x299F31D0, 0x082EFA98, 0xEC4E6C89, + 0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C, 0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917 +}; + +template +const uint64_t blake_constants::c512[16] = { + 0x243F6A8885A308D3ull, 0x13198A2E03707344ull, 0xA4093822299F31D0ull, 0x082EFA98EC4E6C89ull, + 0x452821E638D01377ull, 0xBE5466CF34E90C6Cull, 0xC0AC29B7C97C50DDull, 0x3F84D5B5B5470917ull, + 0x9216D5D98979FB1Bull, 0xD1310BA698DFB5ACull, 0x2FFD72DBD01ADFB7ull, 0xB8E1AFED6A267E96ull, + 0xBA7C9045F12C7F99ull, 0x24A19947B3916CF7ull, 0x0801F2E2858EFC16ull, 0x636920D871574E69ull +}; + +template +const uint32_t blake_constants::S[10][16] = { + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, + { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }, + { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 }, + { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 }, + { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 }, + { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 }, + { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 }, + { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 }, + { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 }, + { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 } +}; + +} // namespace detail + +} // namespace digestpp + +#endif \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/detail/constants/echo_constants.hpp b/ext/include/digestpp/algorithm/detail/constants/echo_constants.hpp new file mode 100644 index 0000000..795826c --- /dev/null +++ b/ext/include/digestpp/algorithm/detail/constants/echo_constants.hpp @@ -0,0 +1,164 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_PROVIDERS_ECHO_CONSTANTS_HPP +#define DIGESTPP_PROVIDERS_ECHO_CONSTANTS_HPP + +namespace digestpp +{ + +namespace detail +{ + +template +struct echo_constants +{ + static const uint32_t T[4][256]; + +}; + +template +const uint32_t echo_constants::T[4][256] = { + { + 0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, 0x0df2f2ff, 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591, + 0x50303060, 0x03010102, 0xa96767ce, 0x7d2b2b56, 0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec, + 0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa, 0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb, + 0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45, 0xbf9c9c23, 0xf7a4a453, 0x967272e4, 0x5bc0c09b, + 0xc2b7b775, 0x1cfdfde1, 0xae93933d, 0x6a26264c, 0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83, + 0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x08f1f1f9, 0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a, + 0x0c040408, 0x52c7c795, 0x65232346, 0x5ec3c39d, 0x28181830, 0xa1969637, 0x0f05050a, 0xb59a9a2f, + 0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df, 0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea, + 0x1b090912, 0x9e83831d, 0x742c2c58, 0x2e1a1a34, 0x2d1b1b36, 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b, + 0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d, 0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413, + 0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1, 0x60202040, 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6, + 0xbe6a6ad4, 0x46cbcb8d, 0xd9bebe67, 0x4b393972, 0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85, + 0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed, 0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511, + 0xcf45458a, 0x10f9f9e9, 0x06020204, 0x817f7ffe, 0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b, + 0xf35151a2, 0xfea3a35d, 0xc0404080, 0x8a8f8f05, 0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1, + 0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142, 0x30101020, 0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf, + 0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3, 0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e, + 0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a, 0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6, + 0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3, 0x66222244, 0x7e2a2a54, 0xab90903b, 0x8388880b, + 0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428, 0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad, + 0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14, 0xdb494992, 0x0a06060c, 0x6c242448, 0xe45c5cb8, + 0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4, 0xa8919139, 0xa4959531, 0x37e4e4d3, 0x8b7979f2, + 0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda, 0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949, + 0xb46c6cd8, 0xfa5656ac, 0x07f4f4f3, 0x25eaeacf, 0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810, + 0xd5baba6f, 0x887878f0, 0x6f25254a, 0x722e2e5c, 0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697, + 0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e, 0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f, + 0x907070e0, 0x423e3e7c, 0xc4b5b571, 0xaa6666cc, 0xd8484890, 0x05030306, 0x01f6f6f7, 0x120e0e1c, + 0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969, 0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27, + 0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122, 0xbb6969d2, 0x70d9d9a9, 0x898e8e07, 0xa7949433, + 0xb69b9b2d, 0x221e1e3c, 0x92878715, 0x20e9e9c9, 0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5, + 0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a, 0xdabfbf65, 0x31e6e6d7, 0xc6424284, 0xb86868d0, + 0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e, 0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c + }, { + 0x6363c6a5, 0x7c7cf884, 0x7777ee99, 0x7b7bf68d, 0xf2f2ff0d, 0x6b6bd6bd, 0x6f6fdeb1, 0xc5c59154, + 0x30306050, 0x01010203, 0x6767cea9, 0x2b2b567d, 0xfefee719, 0xd7d7b562, 0xabab4de6, 0x7676ec9a, + 0xcaca8f45, 0x82821f9d, 0xc9c98940, 0x7d7dfa87, 0xfafaef15, 0x5959b2eb, 0x47478ec9, 0xf0f0fb0b, + 0xadad41ec, 0xd4d4b367, 0xa2a25ffd, 0xafaf45ea, 0x9c9c23bf, 0xa4a453f7, 0x7272e496, 0xc0c09b5b, + 0xb7b775c2, 0xfdfde11c, 0x93933dae, 0x26264c6a, 0x36366c5a, 0x3f3f7e41, 0xf7f7f502, 0xcccc834f, + 0x3434685c, 0xa5a551f4, 0xe5e5d134, 0xf1f1f908, 0x7171e293, 0xd8d8ab73, 0x31316253, 0x15152a3f, + 0x0404080c, 0xc7c79552, 0x23234665, 0xc3c39d5e, 0x18183028, 0x969637a1, 0x05050a0f, 0x9a9a2fb5, + 0x07070e09, 0x12122436, 0x80801b9b, 0xe2e2df3d, 0xebebcd26, 0x27274e69, 0xb2b27fcd, 0x7575ea9f, + 0x0909121b, 0x83831d9e, 0x2c2c5874, 0x1a1a342e, 0x1b1b362d, 0x6e6edcb2, 0x5a5ab4ee, 0xa0a05bfb, + 0x5252a4f6, 0x3b3b764d, 0xd6d6b761, 0xb3b37dce, 0x2929527b, 0xe3e3dd3e, 0x2f2f5e71, 0x84841397, + 0x5353a6f5, 0xd1d1b968, 0x00000000, 0xededc12c, 0x20204060, 0xfcfce31f, 0xb1b179c8, 0x5b5bb6ed, + 0x6a6ad4be, 0xcbcb8d46, 0xbebe67d9, 0x3939724b, 0x4a4a94de, 0x4c4c98d4, 0x5858b0e8, 0xcfcf854a, + 0xd0d0bb6b, 0xefefc52a, 0xaaaa4fe5, 0xfbfbed16, 0x434386c5, 0x4d4d9ad7, 0x33336655, 0x85851194, + 0x45458acf, 0xf9f9e910, 0x02020406, 0x7f7ffe81, 0x5050a0f0, 0x3c3c7844, 0x9f9f25ba, 0xa8a84be3, + 0x5151a2f3, 0xa3a35dfe, 0x404080c0, 0x8f8f058a, 0x92923fad, 0x9d9d21bc, 0x38387048, 0xf5f5f104, + 0xbcbc63df, 0xb6b677c1, 0xdadaaf75, 0x21214263, 0x10102030, 0xffffe51a, 0xf3f3fd0e, 0xd2d2bf6d, + 0xcdcd814c, 0x0c0c1814, 0x13132635, 0xececc32f, 0x5f5fbee1, 0x979735a2, 0x444488cc, 0x17172e39, + 0xc4c49357, 0xa7a755f2, 0x7e7efc82, 0x3d3d7a47, 0x6464c8ac, 0x5d5dbae7, 0x1919322b, 0x7373e695, + 0x6060c0a0, 0x81811998, 0x4f4f9ed1, 0xdcdca37f, 0x22224466, 0x2a2a547e, 0x90903bab, 0x88880b83, + 0x46468cca, 0xeeeec729, 0xb8b86bd3, 0x1414283c, 0xdedea779, 0x5e5ebce2, 0x0b0b161d, 0xdbdbad76, + 0xe0e0db3b, 0x32326456, 0x3a3a744e, 0x0a0a141e, 0x494992db, 0x06060c0a, 0x2424486c, 0x5c5cb8e4, + 0xc2c29f5d, 0xd3d3bd6e, 0xacac43ef, 0x6262c4a6, 0x919139a8, 0x959531a4, 0xe4e4d337, 0x7979f28b, + 0xe7e7d532, 0xc8c88b43, 0x37376e59, 0x6d6ddab7, 0x8d8d018c, 0xd5d5b164, 0x4e4e9cd2, 0xa9a949e0, + 0x6c6cd8b4, 0x5656acfa, 0xf4f4f307, 0xeaeacf25, 0x6565caaf, 0x7a7af48e, 0xaeae47e9, 0x08081018, + 0xbaba6fd5, 0x7878f088, 0x25254a6f, 0x2e2e5c72, 0x1c1c3824, 0xa6a657f1, 0xb4b473c7, 0xc6c69751, + 0xe8e8cb23, 0xdddda17c, 0x7474e89c, 0x1f1f3e21, 0x4b4b96dd, 0xbdbd61dc, 0x8b8b0d86, 0x8a8a0f85, + 0x7070e090, 0x3e3e7c42, 0xb5b571c4, 0x6666ccaa, 0x484890d8, 0x03030605, 0xf6f6f701, 0x0e0e1c12, + 0x6161c2a3, 0x35356a5f, 0x5757aef9, 0xb9b969d0, 0x86861791, 0xc1c19958, 0x1d1d3a27, 0x9e9e27b9, + 0xe1e1d938, 0xf8f8eb13, 0x98982bb3, 0x11112233, 0x6969d2bb, 0xd9d9a970, 0x8e8e0789, 0x949433a7, + 0x9b9b2db6, 0x1e1e3c22, 0x87871592, 0xe9e9c920, 0xcece8749, 0x5555aaff, 0x28285078, 0xdfdfa57a, + 0x8c8c038f, 0xa1a159f8, 0x89890980, 0x0d0d1a17, 0xbfbf65da, 0xe6e6d731, 0x424284c6, 0x6868d0b8, + 0x414182c3, 0x999929b0, 0x2d2d5a77, 0x0f0f1e11, 0xb0b07bcb, 0x5454a8fc, 0xbbbb6dd6, 0x16162c3a + }, { + 0x63c6a563, 0x7cf8847c, 0x77ee9977, 0x7bf68d7b, 0xf2ff0df2, 0x6bd6bd6b, 0x6fdeb16f, 0xc59154c5, + 0x30605030, 0x01020301, 0x67cea967, 0x2b567d2b, 0xfee719fe, 0xd7b562d7, 0xab4de6ab, 0x76ec9a76, + 0xca8f45ca, 0x821f9d82, 0xc98940c9, 0x7dfa877d, 0xfaef15fa, 0x59b2eb59, 0x478ec947, 0xf0fb0bf0, + 0xad41ecad, 0xd4b367d4, 0xa25ffda2, 0xaf45eaaf, 0x9c23bf9c, 0xa453f7a4, 0x72e49672, 0xc09b5bc0, + 0xb775c2b7, 0xfde11cfd, 0x933dae93, 0x264c6a26, 0x366c5a36, 0x3f7e413f, 0xf7f502f7, 0xcc834fcc, + 0x34685c34, 0xa551f4a5, 0xe5d134e5, 0xf1f908f1, 0x71e29371, 0xd8ab73d8, 0x31625331, 0x152a3f15, + 0x04080c04, 0xc79552c7, 0x23466523, 0xc39d5ec3, 0x18302818, 0x9637a196, 0x050a0f05, 0x9a2fb59a, + 0x070e0907, 0x12243612, 0x801b9b80, 0xe2df3de2, 0xebcd26eb, 0x274e6927, 0xb27fcdb2, 0x75ea9f75, + 0x09121b09, 0x831d9e83, 0x2c58742c, 0x1a342e1a, 0x1b362d1b, 0x6edcb26e, 0x5ab4ee5a, 0xa05bfba0, + 0x52a4f652, 0x3b764d3b, 0xd6b761d6, 0xb37dceb3, 0x29527b29, 0xe3dd3ee3, 0x2f5e712f, 0x84139784, + 0x53a6f553, 0xd1b968d1, 0x00000000, 0xedc12ced, 0x20406020, 0xfce31ffc, 0xb179c8b1, 0x5bb6ed5b, + 0x6ad4be6a, 0xcb8d46cb, 0xbe67d9be, 0x39724b39, 0x4a94de4a, 0x4c98d44c, 0x58b0e858, 0xcf854acf, + 0xd0bb6bd0, 0xefc52aef, 0xaa4fe5aa, 0xfbed16fb, 0x4386c543, 0x4d9ad74d, 0x33665533, 0x85119485, + 0x458acf45, 0xf9e910f9, 0x02040602, 0x7ffe817f, 0x50a0f050, 0x3c78443c, 0x9f25ba9f, 0xa84be3a8, + 0x51a2f351, 0xa35dfea3, 0x4080c040, 0x8f058a8f, 0x923fad92, 0x9d21bc9d, 0x38704838, 0xf5f104f5, + 0xbc63dfbc, 0xb677c1b6, 0xdaaf75da, 0x21426321, 0x10203010, 0xffe51aff, 0xf3fd0ef3, 0xd2bf6dd2, + 0xcd814ccd, 0x0c18140c, 0x13263513, 0xecc32fec, 0x5fbee15f, 0x9735a297, 0x4488cc44, 0x172e3917, + 0xc49357c4, 0xa755f2a7, 0x7efc827e, 0x3d7a473d, 0x64c8ac64, 0x5dbae75d, 0x19322b19, 0x73e69573, + 0x60c0a060, 0x81199881, 0x4f9ed14f, 0xdca37fdc, 0x22446622, 0x2a547e2a, 0x903bab90, 0x880b8388, + 0x468cca46, 0xeec729ee, 0xb86bd3b8, 0x14283c14, 0xdea779de, 0x5ebce25e, 0x0b161d0b, 0xdbad76db, + 0xe0db3be0, 0x32645632, 0x3a744e3a, 0x0a141e0a, 0x4992db49, 0x060c0a06, 0x24486c24, 0x5cb8e45c, + 0xc29f5dc2, 0xd3bd6ed3, 0xac43efac, 0x62c4a662, 0x9139a891, 0x9531a495, 0xe4d337e4, 0x79f28b79, + 0xe7d532e7, 0xc88b43c8, 0x376e5937, 0x6ddab76d, 0x8d018c8d, 0xd5b164d5, 0x4e9cd24e, 0xa949e0a9, + 0x6cd8b46c, 0x56acfa56, 0xf4f307f4, 0xeacf25ea, 0x65caaf65, 0x7af48e7a, 0xae47e9ae, 0x08101808, + 0xba6fd5ba, 0x78f08878, 0x254a6f25, 0x2e5c722e, 0x1c38241c, 0xa657f1a6, 0xb473c7b4, 0xc69751c6, + 0xe8cb23e8, 0xdda17cdd, 0x74e89c74, 0x1f3e211f, 0x4b96dd4b, 0xbd61dcbd, 0x8b0d868b, 0x8a0f858a, + 0x70e09070, 0x3e7c423e, 0xb571c4b5, 0x66ccaa66, 0x4890d848, 0x03060503, 0xf6f701f6, 0x0e1c120e, + 0x61c2a361, 0x356a5f35, 0x57aef957, 0xb969d0b9, 0x86179186, 0xc19958c1, 0x1d3a271d, 0x9e27b99e, + 0xe1d938e1, 0xf8eb13f8, 0x982bb398, 0x11223311, 0x69d2bb69, 0xd9a970d9, 0x8e07898e, 0x9433a794, + 0x9b2db69b, 0x1e3c221e, 0x87159287, 0xe9c920e9, 0xce8749ce, 0x55aaff55, 0x28507828, 0xdfa57adf, + 0x8c038f8c, 0xa159f8a1, 0x89098089, 0x0d1a170d, 0xbf65dabf, 0xe6d731e6, 0x4284c642, 0x68d0b868, + 0x4182c341, 0x9929b099, 0x2d5a772d, 0x0f1e110f, 0xb07bcbb0, 0x54a8fc54, 0xbb6dd6bb, 0x162c3a16 + }, { + 0xc6a56363, 0xf8847c7c, 0xee997777, 0xf68d7b7b, 0xff0df2f2, 0xd6bd6b6b, 0xdeb16f6f, 0x9154c5c5, + 0x60503030, 0x02030101, 0xcea96767, 0x567d2b2b, 0xe719fefe, 0xb562d7d7, 0x4de6abab, 0xec9a7676, + 0x8f45caca, 0x1f9d8282, 0x8940c9c9, 0xfa877d7d, 0xef15fafa, 0xb2eb5959, 0x8ec94747, 0xfb0bf0f0, + 0x41ecadad, 0xb367d4d4, 0x5ffda2a2, 0x45eaafaf, 0x23bf9c9c, 0x53f7a4a4, 0xe4967272, 0x9b5bc0c0, + 0x75c2b7b7, 0xe11cfdfd, 0x3dae9393, 0x4c6a2626, 0x6c5a3636, 0x7e413f3f, 0xf502f7f7, 0x834fcccc, + 0x685c3434, 0x51f4a5a5, 0xd134e5e5, 0xf908f1f1, 0xe2937171, 0xab73d8d8, 0x62533131, 0x2a3f1515, + 0x080c0404, 0x9552c7c7, 0x46652323, 0x9d5ec3c3, 0x30281818, 0x37a19696, 0x0a0f0505, 0x2fb59a9a, + 0x0e090707, 0x24361212, 0x1b9b8080, 0xdf3de2e2, 0xcd26ebeb, 0x4e692727, 0x7fcdb2b2, 0xea9f7575, + 0x121b0909, 0x1d9e8383, 0x58742c2c, 0x342e1a1a, 0x362d1b1b, 0xdcb26e6e, 0xb4ee5a5a, 0x5bfba0a0, + 0xa4f65252, 0x764d3b3b, 0xb761d6d6, 0x7dceb3b3, 0x527b2929, 0xdd3ee3e3, 0x5e712f2f, 0x13978484, + 0xa6f55353, 0xb968d1d1, 0x00000000, 0xc12ceded, 0x40602020, 0xe31ffcfc, 0x79c8b1b1, 0xb6ed5b5b, + 0xd4be6a6a, 0x8d46cbcb, 0x67d9bebe, 0x724b3939, 0x94de4a4a, 0x98d44c4c, 0xb0e85858, 0x854acfcf, + 0xbb6bd0d0, 0xc52aefef, 0x4fe5aaaa, 0xed16fbfb, 0x86c54343, 0x9ad74d4d, 0x66553333, 0x11948585, + 0x8acf4545, 0xe910f9f9, 0x04060202, 0xfe817f7f, 0xa0f05050, 0x78443c3c, 0x25ba9f9f, 0x4be3a8a8, + 0xa2f35151, 0x5dfea3a3, 0x80c04040, 0x058a8f8f, 0x3fad9292, 0x21bc9d9d, 0x70483838, 0xf104f5f5, + 0x63dfbcbc, 0x77c1b6b6, 0xaf75dada, 0x42632121, 0x20301010, 0xe51affff, 0xfd0ef3f3, 0xbf6dd2d2, + 0x814ccdcd, 0x18140c0c, 0x26351313, 0xc32fecec, 0xbee15f5f, 0x35a29797, 0x88cc4444, 0x2e391717, + 0x9357c4c4, 0x55f2a7a7, 0xfc827e7e, 0x7a473d3d, 0xc8ac6464, 0xbae75d5d, 0x322b1919, 0xe6957373, + 0xc0a06060, 0x19988181, 0x9ed14f4f, 0xa37fdcdc, 0x44662222, 0x547e2a2a, 0x3bab9090, 0x0b838888, + 0x8cca4646, 0xc729eeee, 0x6bd3b8b8, 0x283c1414, 0xa779dede, 0xbce25e5e, 0x161d0b0b, 0xad76dbdb, + 0xdb3be0e0, 0x64563232, 0x744e3a3a, 0x141e0a0a, 0x92db4949, 0x0c0a0606, 0x486c2424, 0xb8e45c5c, + 0x9f5dc2c2, 0xbd6ed3d3, 0x43efacac, 0xc4a66262, 0x39a89191, 0x31a49595, 0xd337e4e4, 0xf28b7979, + 0xd532e7e7, 0x8b43c8c8, 0x6e593737, 0xdab76d6d, 0x018c8d8d, 0xb164d5d5, 0x9cd24e4e, 0x49e0a9a9, + 0xd8b46c6c, 0xacfa5656, 0xf307f4f4, 0xcf25eaea, 0xcaaf6565, 0xf48e7a7a, 0x47e9aeae, 0x10180808, + 0x6fd5baba, 0xf0887878, 0x4a6f2525, 0x5c722e2e, 0x38241c1c, 0x57f1a6a6, 0x73c7b4b4, 0x9751c6c6, + 0xcb23e8e8, 0xa17cdddd, 0xe89c7474, 0x3e211f1f, 0x96dd4b4b, 0x61dcbdbd, 0x0d868b8b, 0x0f858a8a, + 0xe0907070, 0x7c423e3e, 0x71c4b5b5, 0xccaa6666, 0x90d84848, 0x06050303, 0xf701f6f6, 0x1c120e0e, + 0xc2a36161, 0x6a5f3535, 0xaef95757, 0x69d0b9b9, 0x17918686, 0x9958c1c1, 0x3a271d1d, 0x27b99e9e, + 0xd938e1e1, 0xeb13f8f8, 0x2bb39898, 0x22331111, 0xd2bb6969, 0xa970d9d9, 0x07898e8e, 0x33a79494, + 0x2db69b9b, 0x3c221e1e, 0x15928787, 0xc920e9e9, 0x8749cece, 0xaaff5555, 0x50782828, 0xa57adfdf, + 0x038f8c8c, 0x59f8a1a1, 0x09808989, 0x1a170d0d, 0x65dabfbf, 0xd731e6e6, 0x84c64242, 0xd0b86868, + 0x82c34141, 0x29b09999, 0x5a772d2d, 0x1e110f0f, 0x7bcbb0b0, 0xa8fc5454, 0x6dd6bbbb, 0x2c3a1616 + } + +}; + +} // namespace detail + +} // namespace digestpp + +#endif + diff --git a/ext/include/digestpp/algorithm/detail/constants/esch_constants.hpp b/ext/include/digestpp/algorithm/detail/constants/esch_constants.hpp new file mode 100644 index 0000000..0d9c502 --- /dev/null +++ b/ext/include/digestpp/algorithm/detail/constants/esch_constants.hpp @@ -0,0 +1,29 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_PROVIDERS_ESCH_CONSTANTS_HPP +#define DIGESTPP_PROVIDERS_ESCH_CONSTANTS_HPP + +namespace digestpp +{ + +namespace detail +{ + +template +struct esch_constants +{ + const static uint32_t C[8]; +}; + +template +const uint32_t esch_constants::C[8] = { + 0xb7e15162, 0xbf715880, 0x38b4da56, 0x324e7738, 0xbb1185eb, 0x4f7c7b57, 0xcfbfa1c8, 0xc2b3293d +}; + +} // namespace detail + +} // namespace digestpp + +#endif diff --git a/ext/include/digestpp/algorithm/detail/constants/groestl_constants.hpp b/ext/include/digestpp/algorithm/detail/constants/groestl_constants.hpp new file mode 100644 index 0000000..8e7eff7 --- /dev/null +++ b/ext/include/digestpp/algorithm/detail/constants/groestl_constants.hpp @@ -0,0 +1,557 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_PROVIDERS_GROESTL_CONSTANTS_HPP +#define DIGESTPP_PROVIDERS_GROESTL_CONSTANTS_HPP + +namespace digestpp +{ + +namespace detail +{ + +template +struct groestl_constants +{ + static const uint64_t T[8][256]; + +}; + +template +const uint64_t groestl_constants::T[8][256] = { + { + 0xc6a597f4a5f432c6ull, 0xf884eb9784976ff8ull, 0xee99c7b099b05eeeull, 0xf68df78c8d8c7af6ull, + 0xff0de5170d17e8ffull, 0xd6bdb7dcbddc0ad6ull, 0xdeb1a7c8b1c816deull, 0x915439fc54fc6d91ull, + 0x6050c0f050f09060ull, 0x0203040503050702ull, 0xcea987e0a9e02eceull, 0x567dac877d87d156ull, + 0xe719d52b192bcce7ull, 0xb56271a662a613b5ull, 0x4de69a31e6317c4dull, 0xec9ac3b59ab559ecull, + 0x8f4505cf45cf408full, 0x1f9d3ebc9dbca31full, 0x894009c040c04989ull, 0xfa87ef92879268faull, + 0xef15c53f153fd0efull, 0xb2eb7f26eb2694b2ull, 0x8ec90740c940ce8eull, 0xfb0bed1d0b1de6fbull, + 0x41ec822fec2f6e41ull, 0xb3677da967a91ab3ull, 0x5ffdbe1cfd1c435full, 0x45ea8a25ea256045ull, + 0x23bf46dabfdaf923ull, 0x53f7a602f7025153ull, 0xe496d3a196a145e4ull, 0x9b5b2ded5bed769bull, + 0x75c2ea5dc25d2875ull, 0xe11cd9241c24c5e1ull, 0x3dae7ae9aee9d43dull, 0x4c6a98be6abef24cull, + 0x6c5ad8ee5aee826cull, 0x7e41fcc341c3bd7eull, 0xf502f1060206f3f5ull, 0x834f1dd14fd15283ull, + 0x685cd0e45ce48c68ull, 0x51f4a207f4075651ull, 0xd134b95c345c8dd1ull, 0xf908e9180818e1f9ull, + 0xe293dfae93ae4ce2ull, 0xab734d9573953eabull, 0x6253c4f553f59762ull, 0x2a3f54413f416b2aull, + 0x080c10140c141c08ull, 0x955231f652f66395ull, 0x46658caf65afe946ull, 0x9d5e21e25ee27f9dull, + 0x3028607828784830ull, 0x37a16ef8a1f8cf37ull, 0x0a0f14110f111b0aull, 0x2fb55ec4b5c4eb2full, + 0x0e091c1b091b150eull, 0x2436485a365a7e24ull, 0x1b9b36b69bb6ad1bull, 0xdf3da5473d4798dfull, + 0xcd26816a266aa7cdull, 0x4e699cbb69bbf54eull, 0x7fcdfe4ccd4c337full, 0xea9fcfba9fba50eaull, + 0x121b242d1b2d3f12ull, 0x1d9e3ab99eb9a41dull, 0x5874b09c749cc458ull, 0x342e68722e724634ull, + 0x362d6c772d774136ull, 0xdcb2a3cdb2cd11dcull, 0xb4ee7329ee299db4ull, 0x5bfbb616fb164d5bull, + 0xa4f65301f601a5a4ull, 0x764decd74dd7a176ull, 0xb76175a361a314b7ull, 0x7dcefa49ce49347dull, + 0x527ba48d7b8ddf52ull, 0xdd3ea1423e429fddull, 0x5e71bc937193cd5eull, 0x139726a297a2b113ull, + 0xa6f55704f504a2a6ull, 0xb96869b868b801b9ull, 0x0000000000000000ull, 0xc12c99742c74b5c1ull, + 0x406080a060a0e040ull, 0xe31fdd211f21c2e3ull, 0x79c8f243c8433a79ull, 0xb6ed772ced2c9ab6ull, + 0xd4beb3d9bed90dd4ull, 0x8d4601ca46ca478dull, 0x67d9ce70d9701767ull, 0x724be4dd4bddaf72ull, + 0x94de3379de79ed94ull, 0x98d42b67d467ff98ull, 0xb0e87b23e82393b0ull, 0x854a11de4ade5b85ull, + 0xbb6b6dbd6bbd06bbull, 0xc52a917e2a7ebbc5ull, 0x4fe59e34e5347b4full, 0xed16c13a163ad7edull, + 0x86c51754c554d286ull, 0x9ad72f62d762f89aull, 0x6655ccff55ff9966ull, 0x119422a794a7b611ull, + 0x8acf0f4acf4ac08aull, 0xe910c9301030d9e9ull, 0x0406080a060a0e04ull, 0xfe81e798819866feull, + 0xa0f05b0bf00baba0ull, 0x7844f0cc44ccb478ull, 0x25ba4ad5bad5f025ull, 0x4be3963ee33e754bull, + 0xa2f35f0ef30eaca2ull, 0x5dfeba19fe19445dull, 0x80c01b5bc05bdb80ull, 0x058a0a858a858005ull, + 0x3fad7eecadecd33full, 0x21bc42dfbcdffe21ull, 0x7048e0d848d8a870ull, 0xf104f90c040cfdf1ull, + 0x63dfc67adf7a1963ull, 0x77c1ee58c1582f77ull, 0xaf75459f759f30afull, 0x426384a563a5e742ull, + 0x2030405030507020ull, 0xe51ad12e1a2ecbe5ull, 0xfd0ee1120e12effdull, 0xbf6d65b76db708bfull, + 0x814c19d44cd45581ull, 0x1814303c143c2418ull, 0x26354c5f355f7926ull, 0xc32f9d712f71b2c3ull, + 0xbee16738e13886beull, 0x35a26afda2fdc835ull, 0x88cc0b4fcc4fc788ull, 0x2e395c4b394b652eull, + 0x93573df957f96a93ull, 0x55f2aa0df20d5855ull, 0xfc82e39d829d61fcull, 0x7a47f4c947c9b37aull, + 0xc8ac8befacef27c8ull, 0xbae76f32e73288baull, 0x322b647d2b7d4f32ull, 0xe695d7a495a442e6ull, + 0xc0a09bfba0fb3bc0ull, 0x199832b398b3aa19ull, 0x9ed12768d168f69eull, 0xa37f5d817f8122a3ull, + 0x446688aa66aaee44ull, 0x547ea8827e82d654ull, 0x3bab76e6abe6dd3bull, 0x0b83169e839e950bull, + 0x8cca0345ca45c98cull, 0xc729957b297bbcc7ull, 0x6bd3d66ed36e056bull, 0x283c50443c446c28ull, + 0xa779558b798b2ca7ull, 0xbce2633de23d81bcull, 0x161d2c271d273116ull, 0xad76419a769a37adull, + 0xdb3bad4d3b4d96dbull, 0x6456c8fa56fa9e64ull, 0x744ee8d24ed2a674ull, 0x141e28221e223614ull, + 0x92db3f76db76e492ull, 0x0c0a181e0a1e120cull, 0x486c90b46cb4fc48ull, 0xb8e46b37e4378fb8ull, + 0x9f5d25e75de7789full, 0xbd6e61b26eb20fbdull, 0x43ef862aef2a6943ull, 0xc4a693f1a6f135c4ull, + 0x39a872e3a8e3da39ull, 0x31a462f7a4f7c631ull, 0xd337bd5937598ad3ull, 0xf28bff868b8674f2ull, + 0xd532b156325683d5ull, 0x8b430dc543c54e8bull, 0x6e59dceb59eb856eull, 0xdab7afc2b7c218daull, + 0x018c028f8c8f8e01ull, 0xb16479ac64ac1db1ull, 0x9cd2236dd26df19cull, 0x49e0923be03b7249ull, + 0xd8b4abc7b4c71fd8ull, 0xacfa4315fa15b9acull, 0xf307fd090709faf3ull, 0xcf25856f256fa0cfull, + 0xcaaf8feaafea20caull, 0xf48ef3898e897df4ull, 0x47e98e20e9206747ull, 0x1018202818283810ull, + 0x6fd5de64d5640b6full, 0xf088fb83888373f0ull, 0x4a6f94b16fb1fb4aull, 0x5c72b8967296ca5cull, + 0x3824706c246c5438ull, 0x57f1ae08f1085f57ull, 0x73c7e652c7522173ull, 0x975135f351f36497ull, + 0xcb238d652365aecbull, 0xa17c59847c8425a1ull, 0xe89ccbbf9cbf57e8ull, 0x3e217c6321635d3eull, + 0x96dd377cdd7cea96ull, 0x61dcc27fdc7f1e61ull, 0x0d861a9186919c0dull, 0x0f851e9485949b0full, + 0xe090dbab90ab4be0ull, 0x7c42f8c642c6ba7cull, 0x71c4e257c4572671ull, 0xccaa83e5aae529ccull, + 0x90d83b73d873e390ull, 0x06050c0f050f0906ull, 0xf701f5030103f4f7ull, 0x1c12383612362a1cull, + 0xc2a39ffea3fe3cc2ull, 0x6a5fd4e15fe18b6aull, 0xaef94710f910beaeull, 0x69d0d26bd06b0269ull, + 0x17912ea891a8bf17ull, 0x995829e858e87199ull, 0x3a2774692769533aull, 0x27b94ed0b9d0f727ull, + 0xd938a948384891d9ull, 0xeb13cd351335deebull, 0x2bb356ceb3cee52bull, 0x2233445533557722ull, + 0xd2bbbfd6bbd604d2ull, 0xa9704990709039a9ull, 0x07890e8089808707ull, 0x33a766f2a7f2c133ull, + 0x2db65ac1b6c1ec2dull, 0x3c22786622665a3cull, 0x15922aad92adb815ull, 0xc92089602060a9c9ull, + 0x874915db49db5c87ull, 0xaaff4f1aff1ab0aaull, 0x5078a0887888d850ull, 0xa57a518e7a8e2ba5ull, + 0x038f068a8f8a8903ull, 0x59f8b213f8134a59ull, 0x0980129b809b9209ull, 0x1a1734391739231aull, + 0x65daca75da751065ull, 0xd731b553315384d7ull, 0x84c61351c651d584ull, 0xd0b8bbd3b8d303d0ull, + 0x82c31f5ec35edc82ull, 0x29b052cbb0cbe229ull, 0x5a77b4997799c35aull, 0x1e113c3311332d1eull, + 0x7bcbf646cb463d7bull, 0xa8fc4b1ffc1fb7a8ull, 0x6dd6da61d6610c6dull, 0x2c3a584e3a4e622cull + }, + { + 0xa597f4a5f432c6c6ull, 0x84eb9784976ff8f8ull, 0x99c7b099b05eeeeeull, 0x8df78c8d8c7af6f6ull, + 0x0de5170d17e8ffffull, 0xbdb7dcbddc0ad6d6ull, 0xb1a7c8b1c816dedeull, 0x5439fc54fc6d9191ull, + 0x50c0f050f0906060ull, 0x0304050305070202ull, 0xa987e0a9e02ececeull, 0x7dac877d87d15656ull, + 0x19d52b192bcce7e7ull, 0x6271a662a613b5b5ull, 0xe69a31e6317c4d4dull, 0x9ac3b59ab559ececull, + 0x4505cf45cf408f8full, 0x9d3ebc9dbca31f1full, 0x4009c040c0498989ull, 0x87ef92879268fafaull, + 0x15c53f153fd0efefull, 0xeb7f26eb2694b2b2ull, 0xc90740c940ce8e8eull, 0x0bed1d0b1de6fbfbull, + 0xec822fec2f6e4141ull, 0x677da967a91ab3b3ull, 0xfdbe1cfd1c435f5full, 0xea8a25ea25604545ull, + 0xbf46dabfdaf92323ull, 0xf7a602f702515353ull, 0x96d3a196a145e4e4ull, 0x5b2ded5bed769b9bull, + 0xc2ea5dc25d287575ull, 0x1cd9241c24c5e1e1ull, 0xae7ae9aee9d43d3dull, 0x6a98be6abef24c4cull, + 0x5ad8ee5aee826c6cull, 0x41fcc341c3bd7e7eull, 0x02f1060206f3f5f5ull, 0x4f1dd14fd1528383ull, + 0x5cd0e45ce48c6868ull, 0xf4a207f407565151ull, 0x34b95c345c8dd1d1ull, 0x08e9180818e1f9f9ull, + 0x93dfae93ae4ce2e2ull, 0x734d9573953eababull, 0x53c4f553f5976262ull, 0x3f54413f416b2a2aull, + 0x0c10140c141c0808ull, 0x5231f652f6639595ull, 0x658caf65afe94646ull, 0x5e21e25ee27f9d9dull, + 0x2860782878483030ull, 0xa16ef8a1f8cf3737ull, 0x0f14110f111b0a0aull, 0xb55ec4b5c4eb2f2full, + 0x091c1b091b150e0eull, 0x36485a365a7e2424ull, 0x9b36b69bb6ad1b1bull, 0x3da5473d4798dfdfull, + 0x26816a266aa7cdcdull, 0x699cbb69bbf54e4eull, 0xcdfe4ccd4c337f7full, 0x9fcfba9fba50eaeaull, + 0x1b242d1b2d3f1212ull, 0x9e3ab99eb9a41d1dull, 0x74b09c749cc45858ull, 0x2e68722e72463434ull, + 0x2d6c772d77413636ull, 0xb2a3cdb2cd11dcdcull, 0xee7329ee299db4b4ull, 0xfbb616fb164d5b5bull, + 0xf65301f601a5a4a4ull, 0x4decd74dd7a17676ull, 0x6175a361a314b7b7ull, 0xcefa49ce49347d7dull, + 0x7ba48d7b8ddf5252ull, 0x3ea1423e429fddddull, 0x71bc937193cd5e5eull, 0x9726a297a2b11313ull, + 0xf55704f504a2a6a6ull, 0x6869b868b801b9b9ull, 0x0000000000000000ull, 0x2c99742c74b5c1c1ull, + 0x6080a060a0e04040ull, 0x1fdd211f21c2e3e3ull, 0xc8f243c8433a7979ull, 0xed772ced2c9ab6b6ull, + 0xbeb3d9bed90dd4d4ull, 0x4601ca46ca478d8dull, 0xd9ce70d970176767ull, 0x4be4dd4bddaf7272ull, + 0xde3379de79ed9494ull, 0xd42b67d467ff9898ull, 0xe87b23e82393b0b0ull, 0x4a11de4ade5b8585ull, + 0x6b6dbd6bbd06bbbbull, 0x2a917e2a7ebbc5c5ull, 0xe59e34e5347b4f4full, 0x16c13a163ad7ededull, + 0xc51754c554d28686ull, 0xd72f62d762f89a9aull, 0x55ccff55ff996666ull, 0x9422a794a7b61111ull, + 0xcf0f4acf4ac08a8aull, 0x10c9301030d9e9e9ull, 0x06080a060a0e0404ull, 0x81e798819866fefeull, + 0xf05b0bf00baba0a0ull, 0x44f0cc44ccb47878ull, 0xba4ad5bad5f02525ull, 0xe3963ee33e754b4bull, + 0xf35f0ef30eaca2a2ull, 0xfeba19fe19445d5dull, 0xc01b5bc05bdb8080ull, 0x8a0a858a85800505ull, + 0xad7eecadecd33f3full, 0xbc42dfbcdffe2121ull, 0x48e0d848d8a87070ull, 0x04f90c040cfdf1f1ull, + 0xdfc67adf7a196363ull, 0xc1ee58c1582f7777ull, 0x75459f759f30afafull, 0x6384a563a5e74242ull, + 0x3040503050702020ull, 0x1ad12e1a2ecbe5e5ull, 0x0ee1120e12effdfdull, 0x6d65b76db708bfbfull, + 0x4c19d44cd4558181ull, 0x14303c143c241818ull, 0x354c5f355f792626ull, 0x2f9d712f71b2c3c3ull, + 0xe16738e13886bebeull, 0xa26afda2fdc83535ull, 0xcc0b4fcc4fc78888ull, 0x395c4b394b652e2eull, + 0x573df957f96a9393ull, 0xf2aa0df20d585555ull, 0x82e39d829d61fcfcull, 0x47f4c947c9b37a7aull, + 0xac8befacef27c8c8ull, 0xe76f32e73288babaull, 0x2b647d2b7d4f3232ull, 0x95d7a495a442e6e6ull, + 0xa09bfba0fb3bc0c0ull, 0x9832b398b3aa1919ull, 0xd12768d168f69e9eull, 0x7f5d817f8122a3a3ull, + 0x6688aa66aaee4444ull, 0x7ea8827e82d65454ull, 0xab76e6abe6dd3b3bull, 0x83169e839e950b0bull, + 0xca0345ca45c98c8cull, 0x29957b297bbcc7c7ull, 0xd3d66ed36e056b6bull, 0x3c50443c446c2828ull, + 0x79558b798b2ca7a7ull, 0xe2633de23d81bcbcull, 0x1d2c271d27311616ull, 0x76419a769a37adadull, + 0x3bad4d3b4d96dbdbull, 0x56c8fa56fa9e6464ull, 0x4ee8d24ed2a67474ull, 0x1e28221e22361414ull, + 0xdb3f76db76e49292ull, 0x0a181e0a1e120c0cull, 0x6c90b46cb4fc4848ull, 0xe46b37e4378fb8b8ull, + 0x5d25e75de7789f9full, 0x6e61b26eb20fbdbdull, 0xef862aef2a694343ull, 0xa693f1a6f135c4c4ull, + 0xa872e3a8e3da3939ull, 0xa462f7a4f7c63131ull, 0x37bd5937598ad3d3ull, 0x8bff868b8674f2f2ull, + 0x32b156325683d5d5ull, 0x430dc543c54e8b8bull, 0x59dceb59eb856e6eull, 0xb7afc2b7c218dadaull, + 0x8c028f8c8f8e0101ull, 0x6479ac64ac1db1b1ull, 0xd2236dd26df19c9cull, 0xe0923be03b724949ull, + 0xb4abc7b4c71fd8d8ull, 0xfa4315fa15b9acacull, 0x07fd090709faf3f3ull, 0x25856f256fa0cfcfull, + 0xaf8feaafea20cacaull, 0x8ef3898e897df4f4ull, 0xe98e20e920674747ull, 0x1820281828381010ull, + 0xd5de64d5640b6f6full, 0x88fb83888373f0f0ull, 0x6f94b16fb1fb4a4aull, 0x72b8967296ca5c5cull, + 0x24706c246c543838ull, 0xf1ae08f1085f5757ull, 0xc7e652c752217373ull, 0x5135f351f3649797ull, + 0x238d652365aecbcbull, 0x7c59847c8425a1a1ull, 0x9ccbbf9cbf57e8e8ull, 0x217c6321635d3e3eull, + 0xdd377cdd7cea9696ull, 0xdcc27fdc7f1e6161ull, 0x861a9186919c0d0dull, 0x851e9485949b0f0full, + 0x90dbab90ab4be0e0ull, 0x42f8c642c6ba7c7cull, 0xc4e257c457267171ull, 0xaa83e5aae529ccccull, + 0xd83b73d873e39090ull, 0x050c0f050f090606ull, 0x01f5030103f4f7f7ull, 0x12383612362a1c1cull, + 0xa39ffea3fe3cc2c2ull, 0x5fd4e15fe18b6a6aull, 0xf94710f910beaeaeull, 0xd0d26bd06b026969ull, + 0x912ea891a8bf1717ull, 0x5829e858e8719999ull, 0x2774692769533a3aull, 0xb94ed0b9d0f72727ull, + 0x38a948384891d9d9ull, 0x13cd351335deebebull, 0xb356ceb3cee52b2bull, 0x3344553355772222ull, + 0xbbbfd6bbd604d2d2ull, 0x704990709039a9a9ull, 0x890e808980870707ull, 0xa766f2a7f2c13333ull, + 0xb65ac1b6c1ec2d2dull, 0x22786622665a3c3cull, 0x922aad92adb81515ull, 0x2089602060a9c9c9ull, + 0x4915db49db5c8787ull, 0xff4f1aff1ab0aaaaull, 0x78a0887888d85050ull, 0x7a518e7a8e2ba5a5ull, + 0x8f068a8f8a890303ull, 0xf8b213f8134a5959ull, 0x80129b809b920909ull, 0x1734391739231a1aull, + 0xdaca75da75106565ull, 0x31b553315384d7d7ull, 0xc61351c651d58484ull, 0xb8bbd3b8d303d0d0ull, + 0xc31f5ec35edc8282ull, 0xb052cbb0cbe22929ull, 0x77b4997799c35a5aull, 0x113c3311332d1e1eull, + 0xcbf646cb463d7b7bull, 0xfc4b1ffc1fb7a8a8ull, 0xd6da61d6610c6d6dull, 0x3a584e3a4e622c2cull + }, + { + 0x97f4a5f432c6c6a5ull, 0xeb9784976ff8f884ull, 0xc7b099b05eeeee99ull, 0xf78c8d8c7af6f68dull, + 0xe5170d17e8ffff0dull, 0xb7dcbddc0ad6d6bdull, 0xa7c8b1c816dedeb1ull, 0x39fc54fc6d919154ull, + 0xc0f050f090606050ull, 0x0405030507020203ull, 0x87e0a9e02ececea9ull, 0xac877d87d156567dull, + 0xd52b192bcce7e719ull, 0x71a662a613b5b562ull, 0x9a31e6317c4d4de6ull, 0xc3b59ab559ecec9aull, + 0x05cf45cf408f8f45ull, 0x3ebc9dbca31f1f9dull, 0x09c040c049898940ull, 0xef92879268fafa87ull, + 0xc53f153fd0efef15ull, 0x7f26eb2694b2b2ebull, 0x0740c940ce8e8ec9ull, 0xed1d0b1de6fbfb0bull, + 0x822fec2f6e4141ecull, 0x7da967a91ab3b367ull, 0xbe1cfd1c435f5ffdull, 0x8a25ea25604545eaull, + 0x46dabfdaf92323bfull, 0xa602f702515353f7ull, 0xd3a196a145e4e496ull, 0x2ded5bed769b9b5bull, + 0xea5dc25d287575c2ull, 0xd9241c24c5e1e11cull, 0x7ae9aee9d43d3daeull, 0x98be6abef24c4c6aull, + 0xd8ee5aee826c6c5aull, 0xfcc341c3bd7e7e41ull, 0xf1060206f3f5f502ull, 0x1dd14fd15283834full, + 0xd0e45ce48c68685cull, 0xa207f407565151f4ull, 0xb95c345c8dd1d134ull, 0xe9180818e1f9f908ull, + 0xdfae93ae4ce2e293ull, 0x4d9573953eabab73ull, 0xc4f553f597626253ull, 0x54413f416b2a2a3full, + 0x10140c141c08080cull, 0x31f652f663959552ull, 0x8caf65afe9464665ull, 0x21e25ee27f9d9d5eull, + 0x6078287848303028ull, 0x6ef8a1f8cf3737a1ull, 0x14110f111b0a0a0full, 0x5ec4b5c4eb2f2fb5ull, + 0x1c1b091b150e0e09ull, 0x485a365a7e242436ull, 0x36b69bb6ad1b1b9bull, 0xa5473d4798dfdf3dull, + 0x816a266aa7cdcd26ull, 0x9cbb69bbf54e4e69ull, 0xfe4ccd4c337f7fcdull, 0xcfba9fba50eaea9full, + 0x242d1b2d3f12121bull, 0x3ab99eb9a41d1d9eull, 0xb09c749cc4585874ull, 0x68722e724634342eull, + 0x6c772d774136362dull, 0xa3cdb2cd11dcdcb2ull, 0x7329ee299db4b4eeull, 0xb616fb164d5b5bfbull, + 0x5301f601a5a4a4f6ull, 0xecd74dd7a176764dull, 0x75a361a314b7b761ull, 0xfa49ce49347d7dceull, + 0xa48d7b8ddf52527bull, 0xa1423e429fdddd3eull, 0xbc937193cd5e5e71ull, 0x26a297a2b1131397ull, + 0x5704f504a2a6a6f5ull, 0x69b868b801b9b968ull, 0x0000000000000000ull, 0x99742c74b5c1c12cull, + 0x80a060a0e0404060ull, 0xdd211f21c2e3e31full, 0xf243c8433a7979c8ull, 0x772ced2c9ab6b6edull, + 0xb3d9bed90dd4d4beull, 0x01ca46ca478d8d46ull, 0xce70d970176767d9ull, 0xe4dd4bddaf72724bull, + 0x3379de79ed9494deull, 0x2b67d467ff9898d4ull, 0x7b23e82393b0b0e8ull, 0x11de4ade5b85854aull, + 0x6dbd6bbd06bbbb6bull, 0x917e2a7ebbc5c52aull, 0x9e34e5347b4f4fe5ull, 0xc13a163ad7eded16ull, + 0x1754c554d28686c5ull, 0x2f62d762f89a9ad7ull, 0xccff55ff99666655ull, 0x22a794a7b6111194ull, + 0x0f4acf4ac08a8acfull, 0xc9301030d9e9e910ull, 0x080a060a0e040406ull, 0xe798819866fefe81ull, + 0x5b0bf00baba0a0f0ull, 0xf0cc44ccb4787844ull, 0x4ad5bad5f02525baull, 0x963ee33e754b4be3ull, + 0x5f0ef30eaca2a2f3ull, 0xba19fe19445d5dfeull, 0x1b5bc05bdb8080c0ull, 0x0a858a858005058aull, + 0x7eecadecd33f3fadull, 0x42dfbcdffe2121bcull, 0xe0d848d8a8707048ull, 0xf90c040cfdf1f104ull, + 0xc67adf7a196363dfull, 0xee58c1582f7777c1ull, 0x459f759f30afaf75ull, 0x84a563a5e7424263ull, + 0x4050305070202030ull, 0xd12e1a2ecbe5e51aull, 0xe1120e12effdfd0eull, 0x65b76db708bfbf6dull, + 0x19d44cd45581814cull, 0x303c143c24181814ull, 0x4c5f355f79262635ull, 0x9d712f71b2c3c32full, + 0x6738e13886bebee1ull, 0x6afda2fdc83535a2ull, 0x0b4fcc4fc78888ccull, 0x5c4b394b652e2e39ull, + 0x3df957f96a939357ull, 0xaa0df20d585555f2ull, 0xe39d829d61fcfc82ull, 0xf4c947c9b37a7a47ull, + 0x8befacef27c8c8acull, 0x6f32e73288babae7ull, 0x647d2b7d4f32322bull, 0xd7a495a442e6e695ull, + 0x9bfba0fb3bc0c0a0ull, 0x32b398b3aa191998ull, 0x2768d168f69e9ed1ull, 0x5d817f8122a3a37full, + 0x88aa66aaee444466ull, 0xa8827e82d654547eull, 0x76e6abe6dd3b3babull, 0x169e839e950b0b83ull, + 0x0345ca45c98c8ccaull, 0x957b297bbcc7c729ull, 0xd66ed36e056b6bd3ull, 0x50443c446c28283cull, + 0x558b798b2ca7a779ull, 0x633de23d81bcbce2ull, 0x2c271d273116161dull, 0x419a769a37adad76ull, + 0xad4d3b4d96dbdb3bull, 0xc8fa56fa9e646456ull, 0xe8d24ed2a674744eull, 0x28221e223614141eull, + 0x3f76db76e49292dbull, 0x181e0a1e120c0c0aull, 0x90b46cb4fc48486cull, 0x6b37e4378fb8b8e4ull, + 0x25e75de7789f9f5dull, 0x61b26eb20fbdbd6eull, 0x862aef2a694343efull, 0x93f1a6f135c4c4a6ull, + 0x72e3a8e3da3939a8ull, 0x62f7a4f7c63131a4ull, 0xbd5937598ad3d337ull, 0xff868b8674f2f28bull, + 0xb156325683d5d532ull, 0x0dc543c54e8b8b43ull, 0xdceb59eb856e6e59ull, 0xafc2b7c218dadab7ull, + 0x028f8c8f8e01018cull, 0x79ac64ac1db1b164ull, 0x236dd26df19c9cd2ull, 0x923be03b724949e0ull, + 0xabc7b4c71fd8d8b4ull, 0x4315fa15b9acacfaull, 0xfd090709faf3f307ull, 0x856f256fa0cfcf25ull, + 0x8feaafea20cacaafull, 0xf3898e897df4f48eull, 0x8e20e920674747e9ull, 0x2028182838101018ull, + 0xde64d5640b6f6fd5ull, 0xfb83888373f0f088ull, 0x94b16fb1fb4a4a6full, 0xb8967296ca5c5c72ull, + 0x706c246c54383824ull, 0xae08f1085f5757f1ull, 0xe652c752217373c7ull, 0x35f351f364979751ull, + 0x8d652365aecbcb23ull, 0x59847c8425a1a17cull, 0xcbbf9cbf57e8e89cull, 0x7c6321635d3e3e21ull, + 0x377cdd7cea9696ddull, 0xc27fdc7f1e6161dcull, 0x1a9186919c0d0d86ull, 0x1e9485949b0f0f85ull, + 0xdbab90ab4be0e090ull, 0xf8c642c6ba7c7c42ull, 0xe257c457267171c4ull, 0x83e5aae529ccccaaull, + 0x3b73d873e39090d8ull, 0x0c0f050f09060605ull, 0xf5030103f4f7f701ull, 0x383612362a1c1c12ull, + 0x9ffea3fe3cc2c2a3ull, 0xd4e15fe18b6a6a5full, 0x4710f910beaeaef9ull, 0xd26bd06b026969d0ull, + 0x2ea891a8bf171791ull, 0x29e858e871999958ull, 0x74692769533a3a27ull, 0x4ed0b9d0f72727b9ull, + 0xa948384891d9d938ull, 0xcd351335deebeb13ull, 0x56ceb3cee52b2bb3ull, 0x4455335577222233ull, + 0xbfd6bbd604d2d2bbull, 0x4990709039a9a970ull, 0x0e80898087070789ull, 0x66f2a7f2c13333a7ull, + 0x5ac1b6c1ec2d2db6ull, 0x786622665a3c3c22ull, 0x2aad92adb8151592ull, 0x89602060a9c9c920ull, + 0x15db49db5c878749ull, 0x4f1aff1ab0aaaaffull, 0xa0887888d8505078ull, 0x518e7a8e2ba5a57aull, + 0x068a8f8a8903038full, 0xb213f8134a5959f8ull, 0x129b809b92090980ull, 0x34391739231a1a17ull, + 0xca75da75106565daull, 0xb553315384d7d731ull, 0x1351c651d58484c6ull, 0xbbd3b8d303d0d0b8ull, + 0x1f5ec35edc8282c3ull, 0x52cbb0cbe22929b0ull, 0xb4997799c35a5a77ull, 0x3c3311332d1e1e11ull, + 0xf646cb463d7b7bcbull, 0x4b1ffc1fb7a8a8fcull, 0xda61d6610c6d6dd6ull, 0x584e3a4e622c2c3aull + }, + { + 0xf4a5f432c6c6a597ull, 0x9784976ff8f884ebull, 0xb099b05eeeee99c7ull, 0x8c8d8c7af6f68df7ull, + 0x170d17e8ffff0de5ull, 0xdcbddc0ad6d6bdb7ull, 0xc8b1c816dedeb1a7ull, 0xfc54fc6d91915439ull, + 0xf050f090606050c0ull, 0x0503050702020304ull, 0xe0a9e02ececea987ull, 0x877d87d156567dacull, + 0x2b192bcce7e719d5ull, 0xa662a613b5b56271ull, 0x31e6317c4d4de69aull, 0xb59ab559ecec9ac3ull, + 0xcf45cf408f8f4505ull, 0xbc9dbca31f1f9d3eull, 0xc040c04989894009ull, 0x92879268fafa87efull, + 0x3f153fd0efef15c5ull, 0x26eb2694b2b2eb7full, 0x40c940ce8e8ec907ull, 0x1d0b1de6fbfb0bedull, + 0x2fec2f6e4141ec82ull, 0xa967a91ab3b3677dull, 0x1cfd1c435f5ffdbeull, 0x25ea25604545ea8aull, + 0xdabfdaf92323bf46ull, 0x02f702515353f7a6ull, 0xa196a145e4e496d3ull, 0xed5bed769b9b5b2dull, + 0x5dc25d287575c2eaull, 0x241c24c5e1e11cd9ull, 0xe9aee9d43d3dae7aull, 0xbe6abef24c4c6a98ull, + 0xee5aee826c6c5ad8ull, 0xc341c3bd7e7e41fcull, 0x060206f3f5f502f1ull, 0xd14fd15283834f1dull, + 0xe45ce48c68685cd0ull, 0x07f407565151f4a2ull, 0x5c345c8dd1d134b9ull, 0x180818e1f9f908e9ull, + 0xae93ae4ce2e293dfull, 0x9573953eabab734dull, 0xf553f597626253c4ull, 0x413f416b2a2a3f54ull, + 0x140c141c08080c10ull, 0xf652f66395955231ull, 0xaf65afe94646658cull, 0xe25ee27f9d9d5e21ull, + 0x7828784830302860ull, 0xf8a1f8cf3737a16eull, 0x110f111b0a0a0f14ull, 0xc4b5c4eb2f2fb55eull, + 0x1b091b150e0e091cull, 0x5a365a7e24243648ull, 0xb69bb6ad1b1b9b36ull, 0x473d4798dfdf3da5ull, + 0x6a266aa7cdcd2681ull, 0xbb69bbf54e4e699cull, 0x4ccd4c337f7fcdfeull, 0xba9fba50eaea9fcfull, + 0x2d1b2d3f12121b24ull, 0xb99eb9a41d1d9e3aull, 0x9c749cc4585874b0ull, 0x722e724634342e68ull, + 0x772d774136362d6cull, 0xcdb2cd11dcdcb2a3ull, 0x29ee299db4b4ee73ull, 0x16fb164d5b5bfbb6ull, + 0x01f601a5a4a4f653ull, 0xd74dd7a176764decull, 0xa361a314b7b76175ull, 0x49ce49347d7dcefaull, + 0x8d7b8ddf52527ba4ull, 0x423e429fdddd3ea1ull, 0x937193cd5e5e71bcull, 0xa297a2b113139726ull, + 0x04f504a2a6a6f557ull, 0xb868b801b9b96869ull, 0x0000000000000000ull, 0x742c74b5c1c12c99ull, + 0xa060a0e040406080ull, 0x211f21c2e3e31fddull, 0x43c8433a7979c8f2ull, 0x2ced2c9ab6b6ed77ull, + 0xd9bed90dd4d4beb3ull, 0xca46ca478d8d4601ull, 0x70d970176767d9ceull, 0xdd4bddaf72724be4ull, + 0x79de79ed9494de33ull, 0x67d467ff9898d42bull, 0x23e82393b0b0e87bull, 0xde4ade5b85854a11ull, + 0xbd6bbd06bbbb6b6dull, 0x7e2a7ebbc5c52a91ull, 0x34e5347b4f4fe59eull, 0x3a163ad7eded16c1ull, + 0x54c554d28686c517ull, 0x62d762f89a9ad72full, 0xff55ff99666655ccull, 0xa794a7b611119422ull, + 0x4acf4ac08a8acf0full, 0x301030d9e9e910c9ull, 0x0a060a0e04040608ull, 0x98819866fefe81e7ull, + 0x0bf00baba0a0f05bull, 0xcc44ccb4787844f0ull, 0xd5bad5f02525ba4aull, 0x3ee33e754b4be396ull, + 0x0ef30eaca2a2f35full, 0x19fe19445d5dfebaull, 0x5bc05bdb8080c01bull, 0x858a858005058a0aull, + 0xecadecd33f3fad7eull, 0xdfbcdffe2121bc42ull, 0xd848d8a8707048e0ull, 0x0c040cfdf1f104f9ull, + 0x7adf7a196363dfc6ull, 0x58c1582f7777c1eeull, 0x9f759f30afaf7545ull, 0xa563a5e742426384ull, + 0x5030507020203040ull, 0x2e1a2ecbe5e51ad1ull, 0x120e12effdfd0ee1ull, 0xb76db708bfbf6d65ull, + 0xd44cd45581814c19ull, 0x3c143c2418181430ull, 0x5f355f792626354cull, 0x712f71b2c3c32f9dull, + 0x38e13886bebee167ull, 0xfda2fdc83535a26aull, 0x4fcc4fc78888cc0bull, 0x4b394b652e2e395cull, + 0xf957f96a9393573dull, 0x0df20d585555f2aaull, 0x9d829d61fcfc82e3ull, 0xc947c9b37a7a47f4ull, + 0xefacef27c8c8ac8bull, 0x32e73288babae76full, 0x7d2b7d4f32322b64ull, 0xa495a442e6e695d7ull, + 0xfba0fb3bc0c0a09bull, 0xb398b3aa19199832ull, 0x68d168f69e9ed127ull, 0x817f8122a3a37f5dull, + 0xaa66aaee44446688ull, 0x827e82d654547ea8ull, 0xe6abe6dd3b3bab76ull, 0x9e839e950b0b8316ull, + 0x45ca45c98c8cca03ull, 0x7b297bbcc7c72995ull, 0x6ed36e056b6bd3d6ull, 0x443c446c28283c50ull, + 0x8b798b2ca7a77955ull, 0x3de23d81bcbce263ull, 0x271d273116161d2cull, 0x9a769a37adad7641ull, + 0x4d3b4d96dbdb3badull, 0xfa56fa9e646456c8ull, 0xd24ed2a674744ee8ull, 0x221e223614141e28ull, + 0x76db76e49292db3full, 0x1e0a1e120c0c0a18ull, 0xb46cb4fc48486c90ull, 0x37e4378fb8b8e46bull, + 0xe75de7789f9f5d25ull, 0xb26eb20fbdbd6e61ull, 0x2aef2a694343ef86ull, 0xf1a6f135c4c4a693ull, + 0xe3a8e3da3939a872ull, 0xf7a4f7c63131a462ull, 0x5937598ad3d337bdull, 0x868b8674f2f28bffull, + 0x56325683d5d532b1ull, 0xc543c54e8b8b430dull, 0xeb59eb856e6e59dcull, 0xc2b7c218dadab7afull, + 0x8f8c8f8e01018c02ull, 0xac64ac1db1b16479ull, 0x6dd26df19c9cd223ull, 0x3be03b724949e092ull, + 0xc7b4c71fd8d8b4abull, 0x15fa15b9acacfa43ull, 0x090709faf3f307fdull, 0x6f256fa0cfcf2585ull, + 0xeaafea20cacaaf8full, 0x898e897df4f48ef3ull, 0x20e920674747e98eull, 0x2818283810101820ull, + 0x64d5640b6f6fd5deull, 0x83888373f0f088fbull, 0xb16fb1fb4a4a6f94ull, 0x967296ca5c5c72b8ull, + 0x6c246c5438382470ull, 0x08f1085f5757f1aeull, 0x52c752217373c7e6ull, 0xf351f36497975135ull, + 0x652365aecbcb238dull, 0x847c8425a1a17c59ull, 0xbf9cbf57e8e89ccbull, 0x6321635d3e3e217cull, + 0x7cdd7cea9696dd37ull, 0x7fdc7f1e6161dcc2ull, 0x9186919c0d0d861aull, 0x9485949b0f0f851eull, + 0xab90ab4be0e090dbull, 0xc642c6ba7c7c42f8ull, 0x57c457267171c4e2ull, 0xe5aae529ccccaa83ull, + 0x73d873e39090d83bull, 0x0f050f090606050cull, 0x030103f4f7f701f5ull, 0x3612362a1c1c1238ull, + 0xfea3fe3cc2c2a39full, 0xe15fe18b6a6a5fd4ull, 0x10f910beaeaef947ull, 0x6bd06b026969d0d2ull, + 0xa891a8bf1717912eull, 0xe858e87199995829ull, 0x692769533a3a2774ull, 0xd0b9d0f72727b94eull, + 0x48384891d9d938a9ull, 0x351335deebeb13cdull, 0xceb3cee52b2bb356ull, 0x5533557722223344ull, + 0xd6bbd604d2d2bbbfull, 0x90709039a9a97049ull, 0x808980870707890eull, 0xf2a7f2c13333a766ull, + 0xc1b6c1ec2d2db65aull, 0x6622665a3c3c2278ull, 0xad92adb81515922aull, 0x602060a9c9c92089ull, + 0xdb49db5c87874915ull, 0x1aff1ab0aaaaff4full, 0x887888d8505078a0ull, 0x8e7a8e2ba5a57a51ull, + 0x8a8f8a8903038f06ull, 0x13f8134a5959f8b2ull, 0x9b809b9209098012ull, 0x391739231a1a1734ull, + 0x75da75106565dacaull, 0x53315384d7d731b5ull, 0x51c651d58484c613ull, 0xd3b8d303d0d0b8bbull, + 0x5ec35edc8282c31full, 0xcbb0cbe22929b052ull, 0x997799c35a5a77b4ull, 0x3311332d1e1e113cull, + 0x46cb463d7b7bcbf6ull, 0x1ffc1fb7a8a8fc4bull, 0x61d6610c6d6dd6daull, 0x4e3a4e622c2c3a58ull + }, + { + 0xa5f432c6c6a597f4ull, 0x84976ff8f884eb97ull, 0x99b05eeeee99c7b0ull, 0x8d8c7af6f68df78cull, + 0x0d17e8ffff0de517ull, 0xbddc0ad6d6bdb7dcull, 0xb1c816dedeb1a7c8ull, 0x54fc6d91915439fcull, + 0x50f090606050c0f0ull, 0x0305070202030405ull, 0xa9e02ececea987e0ull, 0x7d87d156567dac87ull, + 0x192bcce7e719d52bull, 0x62a613b5b56271a6ull, 0xe6317c4d4de69a31ull, 0x9ab559ecec9ac3b5ull, + 0x45cf408f8f4505cfull, 0x9dbca31f1f9d3ebcull, 0x40c04989894009c0ull, 0x879268fafa87ef92ull, + 0x153fd0efef15c53full, 0xeb2694b2b2eb7f26ull, 0xc940ce8e8ec90740ull, 0x0b1de6fbfb0bed1dull, + 0xec2f6e4141ec822full, 0x67a91ab3b3677da9ull, 0xfd1c435f5ffdbe1cull, 0xea25604545ea8a25ull, + 0xbfdaf92323bf46daull, 0xf702515353f7a602ull, 0x96a145e4e496d3a1ull, 0x5bed769b9b5b2dedull, + 0xc25d287575c2ea5dull, 0x1c24c5e1e11cd924ull, 0xaee9d43d3dae7ae9ull, 0x6abef24c4c6a98beull, + 0x5aee826c6c5ad8eeull, 0x41c3bd7e7e41fcc3ull, 0x0206f3f5f502f106ull, 0x4fd15283834f1dd1ull, + 0x5ce48c68685cd0e4ull, 0xf407565151f4a207ull, 0x345c8dd1d134b95cull, 0x0818e1f9f908e918ull, + 0x93ae4ce2e293dfaeull, 0x73953eabab734d95ull, 0x53f597626253c4f5ull, 0x3f416b2a2a3f5441ull, + 0x0c141c08080c1014ull, 0x52f66395955231f6ull, 0x65afe94646658cafull, 0x5ee27f9d9d5e21e2ull, + 0x2878483030286078ull, 0xa1f8cf3737a16ef8ull, 0x0f111b0a0a0f1411ull, 0xb5c4eb2f2fb55ec4ull, + 0x091b150e0e091c1bull, 0x365a7e242436485aull, 0x9bb6ad1b1b9b36b6ull, 0x3d4798dfdf3da547ull, + 0x266aa7cdcd26816aull, 0x69bbf54e4e699cbbull, 0xcd4c337f7fcdfe4cull, 0x9fba50eaea9fcfbaull, + 0x1b2d3f12121b242dull, 0x9eb9a41d1d9e3ab9ull, 0x749cc4585874b09cull, 0x2e724634342e6872ull, + 0x2d774136362d6c77ull, 0xb2cd11dcdcb2a3cdull, 0xee299db4b4ee7329ull, 0xfb164d5b5bfbb616ull, + 0xf601a5a4a4f65301ull, 0x4dd7a176764decd7ull, 0x61a314b7b76175a3ull, 0xce49347d7dcefa49ull, + 0x7b8ddf52527ba48dull, 0x3e429fdddd3ea142ull, 0x7193cd5e5e71bc93ull, 0x97a2b113139726a2ull, + 0xf504a2a6a6f55704ull, 0x68b801b9b96869b8ull, 0x0000000000000000ull, 0x2c74b5c1c12c9974ull, + 0x60a0e040406080a0ull, 0x1f21c2e3e31fdd21ull, 0xc8433a7979c8f243ull, 0xed2c9ab6b6ed772cull, + 0xbed90dd4d4beb3d9ull, 0x46ca478d8d4601caull, 0xd970176767d9ce70ull, 0x4bddaf72724be4ddull, + 0xde79ed9494de3379ull, 0xd467ff9898d42b67ull, 0xe82393b0b0e87b23ull, 0x4ade5b85854a11deull, + 0x6bbd06bbbb6b6dbdull, 0x2a7ebbc5c52a917eull, 0xe5347b4f4fe59e34ull, 0x163ad7eded16c13aull, + 0xc554d28686c51754ull, 0xd762f89a9ad72f62ull, 0x55ff99666655ccffull, 0x94a7b611119422a7ull, + 0xcf4ac08a8acf0f4aull, 0x1030d9e9e910c930ull, 0x060a0e040406080aull, 0x819866fefe81e798ull, + 0xf00baba0a0f05b0bull, 0x44ccb4787844f0ccull, 0xbad5f02525ba4ad5ull, 0xe33e754b4be3963eull, + 0xf30eaca2a2f35f0eull, 0xfe19445d5dfeba19ull, 0xc05bdb8080c01b5bull, 0x8a858005058a0a85ull, + 0xadecd33f3fad7eecull, 0xbcdffe2121bc42dfull, 0x48d8a8707048e0d8ull, 0x040cfdf1f104f90cull, + 0xdf7a196363dfc67aull, 0xc1582f7777c1ee58ull, 0x759f30afaf75459full, 0x63a5e742426384a5ull, + 0x3050702020304050ull, 0x1a2ecbe5e51ad12eull, 0x0e12effdfd0ee112ull, 0x6db708bfbf6d65b7ull, + 0x4cd45581814c19d4ull, 0x143c24181814303cull, 0x355f792626354c5full, 0x2f71b2c3c32f9d71ull, + 0xe13886bebee16738ull, 0xa2fdc83535a26afdull, 0xcc4fc78888cc0b4full, 0x394b652e2e395c4bull, + 0x57f96a9393573df9ull, 0xf20d585555f2aa0dull, 0x829d61fcfc82e39dull, 0x47c9b37a7a47f4c9ull, + 0xacef27c8c8ac8befull, 0xe73288babae76f32ull, 0x2b7d4f32322b647dull, 0x95a442e6e695d7a4ull, + 0xa0fb3bc0c0a09bfbull, 0x98b3aa19199832b3ull, 0xd168f69e9ed12768ull, 0x7f8122a3a37f5d81ull, + 0x66aaee44446688aaull, 0x7e82d654547ea882ull, 0xabe6dd3b3bab76e6ull, 0x839e950b0b83169eull, + 0xca45c98c8cca0345ull, 0x297bbcc7c729957bull, 0xd36e056b6bd3d66eull, 0x3c446c28283c5044ull, + 0x798b2ca7a779558bull, 0xe23d81bcbce2633dull, 0x1d273116161d2c27ull, 0x769a37adad76419aull, + 0x3b4d96dbdb3bad4dull, 0x56fa9e646456c8faull, 0x4ed2a674744ee8d2ull, 0x1e223614141e2822ull, + 0xdb76e49292db3f76ull, 0x0a1e120c0c0a181eull, 0x6cb4fc48486c90b4ull, 0xe4378fb8b8e46b37ull, + 0x5de7789f9f5d25e7ull, 0x6eb20fbdbd6e61b2ull, 0xef2a694343ef862aull, 0xa6f135c4c4a693f1ull, + 0xa8e3da3939a872e3ull, 0xa4f7c63131a462f7ull, 0x37598ad3d337bd59ull, 0x8b8674f2f28bff86ull, + 0x325683d5d532b156ull, 0x43c54e8b8b430dc5ull, 0x59eb856e6e59dcebull, 0xb7c218dadab7afc2ull, + 0x8c8f8e01018c028full, 0x64ac1db1b16479acull, 0xd26df19c9cd2236dull, 0xe03b724949e0923bull, + 0xb4c71fd8d8b4abc7ull, 0xfa15b9acacfa4315ull, 0x0709faf3f307fd09ull, 0x256fa0cfcf25856full, + 0xafea20cacaaf8feaull, 0x8e897df4f48ef389ull, 0xe920674747e98e20ull, 0x1828381010182028ull, + 0xd5640b6f6fd5de64ull, 0x888373f0f088fb83ull, 0x6fb1fb4a4a6f94b1ull, 0x7296ca5c5c72b896ull, + 0x246c54383824706cull, 0xf1085f5757f1ae08ull, 0xc752217373c7e652ull, 0x51f36497975135f3ull, + 0x2365aecbcb238d65ull, 0x7c8425a1a17c5984ull, 0x9cbf57e8e89ccbbfull, 0x21635d3e3e217c63ull, + 0xdd7cea9696dd377cull, 0xdc7f1e6161dcc27full, 0x86919c0d0d861a91ull, 0x85949b0f0f851e94ull, + 0x90ab4be0e090dbabull, 0x42c6ba7c7c42f8c6ull, 0xc457267171c4e257ull, 0xaae529ccccaa83e5ull, + 0xd873e39090d83b73ull, 0x050f090606050c0full, 0x0103f4f7f701f503ull, 0x12362a1c1c123836ull, + 0xa3fe3cc2c2a39ffeull, 0x5fe18b6a6a5fd4e1ull, 0xf910beaeaef94710ull, 0xd06b026969d0d26bull, + 0x91a8bf1717912ea8ull, 0x58e87199995829e8ull, 0x2769533a3a277469ull, 0xb9d0f72727b94ed0ull, + 0x384891d9d938a948ull, 0x1335deebeb13cd35ull, 0xb3cee52b2bb356ceull, 0x3355772222334455ull, + 0xbbd604d2d2bbbfd6ull, 0x709039a9a9704990ull, 0x8980870707890e80ull, 0xa7f2c13333a766f2ull, + 0xb6c1ec2d2db65ac1ull, 0x22665a3c3c227866ull, 0x92adb81515922aadull, 0x2060a9c9c9208960ull, + 0x49db5c87874915dbull, 0xff1ab0aaaaff4f1aull, 0x7888d8505078a088ull, 0x7a8e2ba5a57a518eull, + 0x8f8a8903038f068aull, 0xf8134a5959f8b213ull, 0x809b92090980129bull, 0x1739231a1a173439ull, + 0xda75106565daca75ull, 0x315384d7d731b553ull, 0xc651d58484c61351ull, 0xb8d303d0d0b8bbd3ull, + 0xc35edc8282c31f5eull, 0xb0cbe22929b052cbull, 0x7799c35a5a77b499ull, 0x11332d1e1e113c33ull, + 0xcb463d7b7bcbf646ull, 0xfc1fb7a8a8fc4b1full, 0xd6610c6d6dd6da61ull, 0x3a4e622c2c3a584eull + }, + { + 0xf432c6c6a597f4a5ull, 0x976ff8f884eb9784ull, 0xb05eeeee99c7b099ull, 0x8c7af6f68df78c8dull, + 0x17e8ffff0de5170dull, 0xdc0ad6d6bdb7dcbdull, 0xc816dedeb1a7c8b1ull, 0xfc6d91915439fc54ull, + 0xf090606050c0f050ull, 0x0507020203040503ull, 0xe02ececea987e0a9ull, 0x87d156567dac877dull, + 0x2bcce7e719d52b19ull, 0xa613b5b56271a662ull, 0x317c4d4de69a31e6ull, 0xb559ecec9ac3b59aull, + 0xcf408f8f4505cf45ull, 0xbca31f1f9d3ebc9dull, 0xc04989894009c040ull, 0x9268fafa87ef9287ull, + 0x3fd0efef15c53f15ull, 0x2694b2b2eb7f26ebull, 0x40ce8e8ec90740c9ull, 0x1de6fbfb0bed1d0bull, + 0x2f6e4141ec822fecull, 0xa91ab3b3677da967ull, 0x1c435f5ffdbe1cfdull, 0x25604545ea8a25eaull, + 0xdaf92323bf46dabfull, 0x02515353f7a602f7ull, 0xa145e4e496d3a196ull, 0xed769b9b5b2ded5bull, + 0x5d287575c2ea5dc2ull, 0x24c5e1e11cd9241cull, 0xe9d43d3dae7ae9aeull, 0xbef24c4c6a98be6aull, + 0xee826c6c5ad8ee5aull, 0xc3bd7e7e41fcc341ull, 0x06f3f5f502f10602ull, 0xd15283834f1dd14full, + 0xe48c68685cd0e45cull, 0x07565151f4a207f4ull, 0x5c8dd1d134b95c34ull, 0x18e1f9f908e91808ull, + 0xae4ce2e293dfae93ull, 0x953eabab734d9573ull, 0xf597626253c4f553ull, 0x416b2a2a3f54413full, + 0x141c08080c10140cull, 0xf66395955231f652ull, 0xafe94646658caf65ull, 0xe27f9d9d5e21e25eull, + 0x7848303028607828ull, 0xf8cf3737a16ef8a1ull, 0x111b0a0a0f14110full, 0xc4eb2f2fb55ec4b5ull, + 0x1b150e0e091c1b09ull, 0x5a7e242436485a36ull, 0xb6ad1b1b9b36b69bull, 0x4798dfdf3da5473dull, + 0x6aa7cdcd26816a26ull, 0xbbf54e4e699cbb69ull, 0x4c337f7fcdfe4ccdull, 0xba50eaea9fcfba9full, + 0x2d3f12121b242d1bull, 0xb9a41d1d9e3ab99eull, 0x9cc4585874b09c74ull, 0x724634342e68722eull, + 0x774136362d6c772dull, 0xcd11dcdcb2a3cdb2ull, 0x299db4b4ee7329eeull, 0x164d5b5bfbb616fbull, + 0x01a5a4a4f65301f6ull, 0xd7a176764decd74dull, 0xa314b7b76175a361ull, 0x49347d7dcefa49ceull, + 0x8ddf52527ba48d7bull, 0x429fdddd3ea1423eull, 0x93cd5e5e71bc9371ull, 0xa2b113139726a297ull, + 0x04a2a6a6f55704f5ull, 0xb801b9b96869b868ull, 0x0000000000000000ull, 0x74b5c1c12c99742cull, + 0xa0e040406080a060ull, 0x21c2e3e31fdd211full, 0x433a7979c8f243c8ull, 0x2c9ab6b6ed772cedull, + 0xd90dd4d4beb3d9beull, 0xca478d8d4601ca46ull, 0x70176767d9ce70d9ull, 0xddaf72724be4dd4bull, + 0x79ed9494de3379deull, 0x67ff9898d42b67d4ull, 0x2393b0b0e87b23e8ull, 0xde5b85854a11de4aull, + 0xbd06bbbb6b6dbd6bull, 0x7ebbc5c52a917e2aull, 0x347b4f4fe59e34e5ull, 0x3ad7eded16c13a16ull, + 0x54d28686c51754c5ull, 0x62f89a9ad72f62d7ull, 0xff99666655ccff55ull, 0xa7b611119422a794ull, + 0x4ac08a8acf0f4acfull, 0x30d9e9e910c93010ull, 0x0a0e040406080a06ull, 0x9866fefe81e79881ull, + 0x0baba0a0f05b0bf0ull, 0xccb4787844f0cc44ull, 0xd5f02525ba4ad5baull, 0x3e754b4be3963ee3ull, + 0x0eaca2a2f35f0ef3ull, 0x19445d5dfeba19feull, 0x5bdb8080c01b5bc0ull, 0x858005058a0a858aull, + 0xecd33f3fad7eecadull, 0xdffe2121bc42dfbcull, 0xd8a8707048e0d848ull, 0x0cfdf1f104f90c04ull, + 0x7a196363dfc67adfull, 0x582f7777c1ee58c1ull, 0x9f30afaf75459f75ull, 0xa5e742426384a563ull, + 0x5070202030405030ull, 0x2ecbe5e51ad12e1aull, 0x12effdfd0ee1120eull, 0xb708bfbf6d65b76dull, + 0xd45581814c19d44cull, 0x3c24181814303c14ull, 0x5f792626354c5f35ull, 0x71b2c3c32f9d712full, + 0x3886bebee16738e1ull, 0xfdc83535a26afda2ull, 0x4fc78888cc0b4fccull, 0x4b652e2e395c4b39ull, + 0xf96a9393573df957ull, 0x0d585555f2aa0df2ull, 0x9d61fcfc82e39d82ull, 0xc9b37a7a47f4c947ull, + 0xef27c8c8ac8befacull, 0x3288babae76f32e7ull, 0x7d4f32322b647d2bull, 0xa442e6e695d7a495ull, + 0xfb3bc0c0a09bfba0ull, 0xb3aa19199832b398ull, 0x68f69e9ed12768d1ull, 0x8122a3a37f5d817full, + 0xaaee44446688aa66ull, 0x82d654547ea8827eull, 0xe6dd3b3bab76e6abull, 0x9e950b0b83169e83ull, + 0x45c98c8cca0345caull, 0x7bbcc7c729957b29ull, 0x6e056b6bd3d66ed3ull, 0x446c28283c50443cull, + 0x8b2ca7a779558b79ull, 0x3d81bcbce2633de2ull, 0x273116161d2c271dull, 0x9a37adad76419a76ull, + 0x4d96dbdb3bad4d3bull, 0xfa9e646456c8fa56ull, 0xd2a674744ee8d24eull, 0x223614141e28221eull, + 0x76e49292db3f76dbull, 0x1e120c0c0a181e0aull, 0xb4fc48486c90b46cull, 0x378fb8b8e46b37e4ull, + 0xe7789f9f5d25e75dull, 0xb20fbdbd6e61b26eull, 0x2a694343ef862aefull, 0xf135c4c4a693f1a6ull, + 0xe3da3939a872e3a8ull, 0xf7c63131a462f7a4ull, 0x598ad3d337bd5937ull, 0x8674f2f28bff868bull, + 0x5683d5d532b15632ull, 0xc54e8b8b430dc543ull, 0xeb856e6e59dceb59ull, 0xc218dadab7afc2b7ull, + 0x8f8e01018c028f8cull, 0xac1db1b16479ac64ull, 0x6df19c9cd2236dd2ull, 0x3b724949e0923be0ull, + 0xc71fd8d8b4abc7b4ull, 0x15b9acacfa4315faull, 0x09faf3f307fd0907ull, 0x6fa0cfcf25856f25ull, + 0xea20cacaaf8feaafull, 0x897df4f48ef3898eull, 0x20674747e98e20e9ull, 0x2838101018202818ull, + 0x640b6f6fd5de64d5ull, 0x8373f0f088fb8388ull, 0xb1fb4a4a6f94b16full, 0x96ca5c5c72b89672ull, + 0x6c54383824706c24ull, 0x085f5757f1ae08f1ull, 0x52217373c7e652c7ull, 0xf36497975135f351ull, + 0x65aecbcb238d6523ull, 0x8425a1a17c59847cull, 0xbf57e8e89ccbbf9cull, 0x635d3e3e217c6321ull, + 0x7cea9696dd377cddull, 0x7f1e6161dcc27fdcull, 0x919c0d0d861a9186ull, 0x949b0f0f851e9485ull, + 0xab4be0e090dbab90ull, 0xc6ba7c7c42f8c642ull, 0x57267171c4e257c4ull, 0xe529ccccaa83e5aaull, + 0x73e39090d83b73d8ull, 0x0f090606050c0f05ull, 0x03f4f7f701f50301ull, 0x362a1c1c12383612ull, + 0xfe3cc2c2a39ffea3ull, 0xe18b6a6a5fd4e15full, 0x10beaeaef94710f9ull, 0x6b026969d0d26bd0ull, + 0xa8bf1717912ea891ull, 0xe87199995829e858ull, 0x69533a3a27746927ull, 0xd0f72727b94ed0b9ull, + 0x4891d9d938a94838ull, 0x35deebeb13cd3513ull, 0xcee52b2bb356ceb3ull, 0x5577222233445533ull, + 0xd604d2d2bbbfd6bbull, 0x9039a9a970499070ull, 0x80870707890e8089ull, 0xf2c13333a766f2a7ull, + 0xc1ec2d2db65ac1b6ull, 0x665a3c3c22786622ull, 0xadb81515922aad92ull, 0x60a9c9c920896020ull, + 0xdb5c87874915db49ull, 0x1ab0aaaaff4f1affull, 0x88d8505078a08878ull, 0x8e2ba5a57a518e7aull, + 0x8a8903038f068a8full, 0x134a5959f8b213f8ull, 0x9b92090980129b80ull, 0x39231a1a17343917ull, + 0x75106565daca75daull, 0x5384d7d731b55331ull, 0x51d58484c61351c6ull, 0xd303d0d0b8bbd3b8ull, + 0x5edc8282c31f5ec3ull, 0xcbe22929b052cbb0ull, 0x99c35a5a77b49977ull, 0x332d1e1e113c3311ull, + 0x463d7b7bcbf646cbull, 0x1fb7a8a8fc4b1ffcull, 0x610c6d6dd6da61d6ull, 0x4e622c2c3a584e3aull + }, + { + 0x32c6c6a597f4a5f4ull, 0x6ff8f884eb978497ull, 0x5eeeee99c7b099b0ull, 0x7af6f68df78c8d8cull, + 0xe8ffff0de5170d17ull, 0x0ad6d6bdb7dcbddcull, 0x16dedeb1a7c8b1c8ull, 0x6d91915439fc54fcull, + 0x90606050c0f050f0ull, 0x0702020304050305ull, 0x2ececea987e0a9e0ull, 0xd156567dac877d87ull, + 0xcce7e719d52b192bull, 0x13b5b56271a662a6ull, 0x7c4d4de69a31e631ull, 0x59ecec9ac3b59ab5ull, + 0x408f8f4505cf45cfull, 0xa31f1f9d3ebc9dbcull, 0x4989894009c040c0ull, 0x68fafa87ef928792ull, + 0xd0efef15c53f153full, 0x94b2b2eb7f26eb26ull, 0xce8e8ec90740c940ull, 0xe6fbfb0bed1d0b1dull, + 0x6e4141ec822fec2full, 0x1ab3b3677da967a9ull, 0x435f5ffdbe1cfd1cull, 0x604545ea8a25ea25ull, + 0xf92323bf46dabfdaull, 0x515353f7a602f702ull, 0x45e4e496d3a196a1ull, 0x769b9b5b2ded5bedull, + 0x287575c2ea5dc25dull, 0xc5e1e11cd9241c24ull, 0xd43d3dae7ae9aee9ull, 0xf24c4c6a98be6abeull, + 0x826c6c5ad8ee5aeeull, 0xbd7e7e41fcc341c3ull, 0xf3f5f502f1060206ull, 0x5283834f1dd14fd1ull, + 0x8c68685cd0e45ce4ull, 0x565151f4a207f407ull, 0x8dd1d134b95c345cull, 0xe1f9f908e9180818ull, + 0x4ce2e293dfae93aeull, 0x3eabab734d957395ull, 0x97626253c4f553f5ull, 0x6b2a2a3f54413f41ull, + 0x1c08080c10140c14ull, 0x6395955231f652f6ull, 0xe94646658caf65afull, 0x7f9d9d5e21e25ee2ull, + 0x4830302860782878ull, 0xcf3737a16ef8a1f8ull, 0x1b0a0a0f14110f11ull, 0xeb2f2fb55ec4b5c4ull, + 0x150e0e091c1b091bull, 0x7e242436485a365aull, 0xad1b1b9b36b69bb6ull, 0x98dfdf3da5473d47ull, + 0xa7cdcd26816a266aull, 0xf54e4e699cbb69bbull, 0x337f7fcdfe4ccd4cull, 0x50eaea9fcfba9fbaull, + 0x3f12121b242d1b2dull, 0xa41d1d9e3ab99eb9ull, 0xc4585874b09c749cull, 0x4634342e68722e72ull, + 0x4136362d6c772d77ull, 0x11dcdcb2a3cdb2cdull, 0x9db4b4ee7329ee29ull, 0x4d5b5bfbb616fb16ull, + 0xa5a4a4f65301f601ull, 0xa176764decd74dd7ull, 0x14b7b76175a361a3ull, 0x347d7dcefa49ce49ull, + 0xdf52527ba48d7b8dull, 0x9fdddd3ea1423e42ull, 0xcd5e5e71bc937193ull, 0xb113139726a297a2ull, + 0xa2a6a6f55704f504ull, 0x01b9b96869b868b8ull, 0x0000000000000000ull, 0xb5c1c12c99742c74ull, + 0xe040406080a060a0ull, 0xc2e3e31fdd211f21ull, 0x3a7979c8f243c843ull, 0x9ab6b6ed772ced2cull, + 0x0dd4d4beb3d9bed9ull, 0x478d8d4601ca46caull, 0x176767d9ce70d970ull, 0xaf72724be4dd4bddull, + 0xed9494de3379de79ull, 0xff9898d42b67d467ull, 0x93b0b0e87b23e823ull, 0x5b85854a11de4adeull, + 0x06bbbb6b6dbd6bbdull, 0xbbc5c52a917e2a7eull, 0x7b4f4fe59e34e534ull, 0xd7eded16c13a163aull, + 0xd28686c51754c554ull, 0xf89a9ad72f62d762ull, 0x99666655ccff55ffull, 0xb611119422a794a7ull, + 0xc08a8acf0f4acf4aull, 0xd9e9e910c9301030ull, 0x0e040406080a060aull, 0x66fefe81e7988198ull, + 0xaba0a0f05b0bf00bull, 0xb4787844f0cc44ccull, 0xf02525ba4ad5bad5ull, 0x754b4be3963ee33eull, + 0xaca2a2f35f0ef30eull, 0x445d5dfeba19fe19ull, 0xdb8080c01b5bc05bull, 0x8005058a0a858a85ull, + 0xd33f3fad7eecadecull, 0xfe2121bc42dfbcdfull, 0xa8707048e0d848d8ull, 0xfdf1f104f90c040cull, + 0x196363dfc67adf7aull, 0x2f7777c1ee58c158ull, 0x30afaf75459f759full, 0xe742426384a563a5ull, + 0x7020203040503050ull, 0xcbe5e51ad12e1a2eull, 0xeffdfd0ee1120e12ull, 0x08bfbf6d65b76db7ull, + 0x5581814c19d44cd4ull, 0x24181814303c143cull, 0x792626354c5f355full, 0xb2c3c32f9d712f71ull, + 0x86bebee16738e138ull, 0xc83535a26afda2fdull, 0xc78888cc0b4fcc4full, 0x652e2e395c4b394bull, + 0x6a9393573df957f9ull, 0x585555f2aa0df20dull, 0x61fcfc82e39d829dull, 0xb37a7a47f4c947c9ull, + 0x27c8c8ac8befacefull, 0x88babae76f32e732ull, 0x4f32322b647d2b7dull, 0x42e6e695d7a495a4ull, + 0x3bc0c0a09bfba0fbull, 0xaa19199832b398b3ull, 0xf69e9ed12768d168ull, 0x22a3a37f5d817f81ull, + 0xee44446688aa66aaull, 0xd654547ea8827e82ull, 0xdd3b3bab76e6abe6ull, 0x950b0b83169e839eull, + 0xc98c8cca0345ca45ull, 0xbcc7c729957b297bull, 0x056b6bd3d66ed36eull, 0x6c28283c50443c44ull, + 0x2ca7a779558b798bull, 0x81bcbce2633de23dull, 0x3116161d2c271d27ull, 0x37adad76419a769aull, + 0x96dbdb3bad4d3b4dull, 0x9e646456c8fa56faull, 0xa674744ee8d24ed2ull, 0x3614141e28221e22ull, + 0xe49292db3f76db76ull, 0x120c0c0a181e0a1eull, 0xfc48486c90b46cb4ull, 0x8fb8b8e46b37e437ull, + 0x789f9f5d25e75de7ull, 0x0fbdbd6e61b26eb2ull, 0x694343ef862aef2aull, 0x35c4c4a693f1a6f1ull, + 0xda3939a872e3a8e3ull, 0xc63131a462f7a4f7ull, 0x8ad3d337bd593759ull, 0x74f2f28bff868b86ull, + 0x83d5d532b1563256ull, 0x4e8b8b430dc543c5ull, 0x856e6e59dceb59ebull, 0x18dadab7afc2b7c2ull, + 0x8e01018c028f8c8full, 0x1db1b16479ac64acull, 0xf19c9cd2236dd26dull, 0x724949e0923be03bull, + 0x1fd8d8b4abc7b4c7ull, 0xb9acacfa4315fa15ull, 0xfaf3f307fd090709ull, 0xa0cfcf25856f256full, + 0x20cacaaf8feaafeaull, 0x7df4f48ef3898e89ull, 0x674747e98e20e920ull, 0x3810101820281828ull, + 0x0b6f6fd5de64d564ull, 0x73f0f088fb838883ull, 0xfb4a4a6f94b16fb1ull, 0xca5c5c72b8967296ull, + 0x54383824706c246cull, 0x5f5757f1ae08f108ull, 0x217373c7e652c752ull, 0x6497975135f351f3ull, + 0xaecbcb238d652365ull, 0x25a1a17c59847c84ull, 0x57e8e89ccbbf9cbfull, 0x5d3e3e217c632163ull, + 0xea9696dd377cdd7cull, 0x1e6161dcc27fdc7full, 0x9c0d0d861a918691ull, 0x9b0f0f851e948594ull, + 0x4be0e090dbab90abull, 0xba7c7c42f8c642c6ull, 0x267171c4e257c457ull, 0x29ccccaa83e5aae5ull, + 0xe39090d83b73d873ull, 0x090606050c0f050full, 0xf4f7f701f5030103ull, 0x2a1c1c1238361236ull, + 0x3cc2c2a39ffea3feull, 0x8b6a6a5fd4e15fe1ull, 0xbeaeaef94710f910ull, 0x026969d0d26bd06bull, + 0xbf1717912ea891a8ull, 0x7199995829e858e8ull, 0x533a3a2774692769ull, 0xf72727b94ed0b9d0ull, + 0x91d9d938a9483848ull, 0xdeebeb13cd351335ull, 0xe52b2bb356ceb3ceull, 0x7722223344553355ull, + 0x04d2d2bbbfd6bbd6ull, 0x39a9a97049907090ull, 0x870707890e808980ull, 0xc13333a766f2a7f2ull, + 0xec2d2db65ac1b6c1ull, 0x5a3c3c2278662266ull, 0xb81515922aad92adull, 0xa9c9c92089602060ull, + 0x5c87874915db49dbull, 0xb0aaaaff4f1aff1aull, 0xd8505078a0887888ull, 0x2ba5a57a518e7a8eull, + 0x8903038f068a8f8aull, 0x4a5959f8b213f813ull, 0x92090980129b809bull, 0x231a1a1734391739ull, + 0x106565daca75da75ull, 0x84d7d731b5533153ull, 0xd58484c61351c651ull, 0x03d0d0b8bbd3b8d3ull, + 0xdc8282c31f5ec35eull, 0xe22929b052cbb0cbull, 0xc35a5a77b4997799ull, 0x2d1e1e113c331133ull, + 0x3d7b7bcbf646cb46ull, 0xb7a8a8fc4b1ffc1full, 0x0c6d6dd6da61d661ull, 0x622c2c3a584e3a4eull + }, + { + 0xc6c6a597f4a5f432ull, 0xf8f884eb9784976full, 0xeeee99c7b099b05eull, 0xf6f68df78c8d8c7aull, + 0xffff0de5170d17e8ull, 0xd6d6bdb7dcbddc0aull, 0xdedeb1a7c8b1c816ull, 0x91915439fc54fc6dull, + 0x606050c0f050f090ull, 0x0202030405030507ull, 0xcecea987e0a9e02eull, 0x56567dac877d87d1ull, + 0xe7e719d52b192bccull, 0xb5b56271a662a613ull, 0x4d4de69a31e6317cull, 0xecec9ac3b59ab559ull, + 0x8f8f4505cf45cf40ull, 0x1f1f9d3ebc9dbca3ull, 0x89894009c040c049ull, 0xfafa87ef92879268ull, + 0xefef15c53f153fd0ull, 0xb2b2eb7f26eb2694ull, 0x8e8ec90740c940ceull, 0xfbfb0bed1d0b1de6ull, + 0x4141ec822fec2f6eull, 0xb3b3677da967a91aull, 0x5f5ffdbe1cfd1c43ull, 0x4545ea8a25ea2560ull, + 0x2323bf46dabfdaf9ull, 0x5353f7a602f70251ull, 0xe4e496d3a196a145ull, 0x9b9b5b2ded5bed76ull, + 0x7575c2ea5dc25d28ull, 0xe1e11cd9241c24c5ull, 0x3d3dae7ae9aee9d4ull, 0x4c4c6a98be6abef2ull, + 0x6c6c5ad8ee5aee82ull, 0x7e7e41fcc341c3bdull, 0xf5f502f1060206f3ull, 0x83834f1dd14fd152ull, + 0x68685cd0e45ce48cull, 0x5151f4a207f40756ull, 0xd1d134b95c345c8dull, 0xf9f908e9180818e1ull, + 0xe2e293dfae93ae4cull, 0xabab734d9573953eull, 0x626253c4f553f597ull, 0x2a2a3f54413f416bull, + 0x08080c10140c141cull, 0x95955231f652f663ull, 0x4646658caf65afe9ull, 0x9d9d5e21e25ee27full, + 0x3030286078287848ull, 0x3737a16ef8a1f8cfull, 0x0a0a0f14110f111bull, 0x2f2fb55ec4b5c4ebull, + 0x0e0e091c1b091b15ull, 0x242436485a365a7eull, 0x1b1b9b36b69bb6adull, 0xdfdf3da5473d4798ull, + 0xcdcd26816a266aa7ull, 0x4e4e699cbb69bbf5ull, 0x7f7fcdfe4ccd4c33ull, 0xeaea9fcfba9fba50ull, + 0x12121b242d1b2d3full, 0x1d1d9e3ab99eb9a4ull, 0x585874b09c749cc4ull, 0x34342e68722e7246ull, + 0x36362d6c772d7741ull, 0xdcdcb2a3cdb2cd11ull, 0xb4b4ee7329ee299dull, 0x5b5bfbb616fb164dull, + 0xa4a4f65301f601a5ull, 0x76764decd74dd7a1ull, 0xb7b76175a361a314ull, 0x7d7dcefa49ce4934ull, + 0x52527ba48d7b8ddfull, 0xdddd3ea1423e429full, 0x5e5e71bc937193cdull, 0x13139726a297a2b1ull, + 0xa6a6f55704f504a2ull, 0xb9b96869b868b801ull, 0x0000000000000000ull, 0xc1c12c99742c74b5ull, + 0x40406080a060a0e0ull, 0xe3e31fdd211f21c2ull, 0x7979c8f243c8433aull, 0xb6b6ed772ced2c9aull, + 0xd4d4beb3d9bed90dull, 0x8d8d4601ca46ca47ull, 0x6767d9ce70d97017ull, 0x72724be4dd4bddafull, + 0x9494de3379de79edull, 0x9898d42b67d467ffull, 0xb0b0e87b23e82393ull, 0x85854a11de4ade5bull, + 0xbbbb6b6dbd6bbd06ull, 0xc5c52a917e2a7ebbull, 0x4f4fe59e34e5347bull, 0xeded16c13a163ad7ull, + 0x8686c51754c554d2ull, 0x9a9ad72f62d762f8ull, 0x666655ccff55ff99ull, 0x11119422a794a7b6ull, + 0x8a8acf0f4acf4ac0ull, 0xe9e910c9301030d9ull, 0x040406080a060a0eull, 0xfefe81e798819866ull, + 0xa0a0f05b0bf00babull, 0x787844f0cc44ccb4ull, 0x2525ba4ad5bad5f0ull, 0x4b4be3963ee33e75ull, + 0xa2a2f35f0ef30eacull, 0x5d5dfeba19fe1944ull, 0x8080c01b5bc05bdbull, 0x05058a0a858a8580ull, + 0x3f3fad7eecadecd3ull, 0x2121bc42dfbcdffeull, 0x707048e0d848d8a8ull, 0xf1f104f90c040cfdull, + 0x6363dfc67adf7a19ull, 0x7777c1ee58c1582full, 0xafaf75459f759f30ull, 0x42426384a563a5e7ull, + 0x2020304050305070ull, 0xe5e51ad12e1a2ecbull, 0xfdfd0ee1120e12efull, 0xbfbf6d65b76db708ull, + 0x81814c19d44cd455ull, 0x181814303c143c24ull, 0x2626354c5f355f79ull, 0xc3c32f9d712f71b2ull, + 0xbebee16738e13886ull, 0x3535a26afda2fdc8ull, 0x8888cc0b4fcc4fc7ull, 0x2e2e395c4b394b65ull, + 0x9393573df957f96aull, 0x5555f2aa0df20d58ull, 0xfcfc82e39d829d61ull, 0x7a7a47f4c947c9b3ull, + 0xc8c8ac8befacef27ull, 0xbabae76f32e73288ull, 0x32322b647d2b7d4full, 0xe6e695d7a495a442ull, + 0xc0c0a09bfba0fb3bull, 0x19199832b398b3aaull, 0x9e9ed12768d168f6ull, 0xa3a37f5d817f8122ull, + 0x44446688aa66aaeeull, 0x54547ea8827e82d6ull, 0x3b3bab76e6abe6ddull, 0x0b0b83169e839e95ull, + 0x8c8cca0345ca45c9ull, 0xc7c729957b297bbcull, 0x6b6bd3d66ed36e05ull, 0x28283c50443c446cull, + 0xa7a779558b798b2cull, 0xbcbce2633de23d81ull, 0x16161d2c271d2731ull, 0xadad76419a769a37ull, + 0xdbdb3bad4d3b4d96ull, 0x646456c8fa56fa9eull, 0x74744ee8d24ed2a6ull, 0x14141e28221e2236ull, + 0x9292db3f76db76e4ull, 0x0c0c0a181e0a1e12ull, 0x48486c90b46cb4fcull, 0xb8b8e46b37e4378full, + 0x9f9f5d25e75de778ull, 0xbdbd6e61b26eb20full, 0x4343ef862aef2a69ull, 0xc4c4a693f1a6f135ull, + 0x3939a872e3a8e3daull, 0x3131a462f7a4f7c6ull, 0xd3d337bd5937598aull, 0xf2f28bff868b8674ull, + 0xd5d532b156325683ull, 0x8b8b430dc543c54eull, 0x6e6e59dceb59eb85ull, 0xdadab7afc2b7c218ull, + 0x01018c028f8c8f8eull, 0xb1b16479ac64ac1dull, 0x9c9cd2236dd26df1ull, 0x4949e0923be03b72ull, + 0xd8d8b4abc7b4c71full, 0xacacfa4315fa15b9ull, 0xf3f307fd090709faull, 0xcfcf25856f256fa0ull, + 0xcacaaf8feaafea20ull, 0xf4f48ef3898e897dull, 0x4747e98e20e92067ull, 0x1010182028182838ull, + 0x6f6fd5de64d5640bull, 0xf0f088fb83888373ull, 0x4a4a6f94b16fb1fbull, 0x5c5c72b8967296caull, + 0x383824706c246c54ull, 0x5757f1ae08f1085full, 0x7373c7e652c75221ull, 0x97975135f351f364ull, + 0xcbcb238d652365aeull, 0xa1a17c59847c8425ull, 0xe8e89ccbbf9cbf57ull, 0x3e3e217c6321635dull, + 0x9696dd377cdd7ceaull, 0x6161dcc27fdc7f1eull, 0x0d0d861a9186919cull, 0x0f0f851e9485949bull, + 0xe0e090dbab90ab4bull, 0x7c7c42f8c642c6baull, 0x7171c4e257c45726ull, 0xccccaa83e5aae529ull, + 0x9090d83b73d873e3ull, 0x0606050c0f050f09ull, 0xf7f701f5030103f4ull, 0x1c1c12383612362aull, + 0xc2c2a39ffea3fe3cull, 0x6a6a5fd4e15fe18bull, 0xaeaef94710f910beull, 0x6969d0d26bd06b02ull, + 0x1717912ea891a8bfull, 0x99995829e858e871ull, 0x3a3a277469276953ull, 0x2727b94ed0b9d0f7ull, + 0xd9d938a948384891ull, 0xebeb13cd351335deull, 0x2b2bb356ceb3cee5ull, 0x2222334455335577ull, + 0xd2d2bbbfd6bbd604ull, 0xa9a9704990709039ull, 0x0707890e80898087ull, 0x3333a766f2a7f2c1ull, + 0x2d2db65ac1b6c1ecull, 0x3c3c22786622665aull, 0x1515922aad92adb8ull, 0xc9c92089602060a9ull, + 0x87874915db49db5cull, 0xaaaaff4f1aff1ab0ull, 0x505078a0887888d8ull, 0xa5a57a518e7a8e2bull, + 0x03038f068a8f8a89ull, 0x5959f8b213f8134aull, 0x090980129b809b92ull, 0x1a1a173439173923ull, + 0x6565daca75da7510ull, 0xd7d731b553315384ull, 0x8484c61351c651d5ull, 0xd0d0b8bbd3b8d303ull, + 0x8282c31f5ec35edcull, 0x2929b052cbb0cbe2ull, 0x5a5a77b4997799c3ull, 0x1e1e113c3311332dull, + 0x7b7bcbf646cb463dull, 0xa8a8fc4b1ffc1fb7ull, 0x6d6dd6da61d6610cull, 0x2c2c3a584e3a4e62ull + } +}; + +} // namespace detail + +} // namespace digestpp + +#endif \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/detail/constants/jh_constants.hpp b/ext/include/digestpp/algorithm/detail/constants/jh_constants.hpp new file mode 100644 index 0000000..9d8d563 --- /dev/null +++ b/ext/include/digestpp/algorithm/detail/constants/jh_constants.hpp @@ -0,0 +1,71 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_PROVIDERS_JH_CONSTANTS_HPP +#define DIGESTPP_PROVIDERS_JH_CONSTANTS_HPP + +namespace digestpp +{ + +namespace detail +{ + +template +struct jh_constants +{ + static const uint64_t C[168]; + +}; + +template +const uint64_t jh_constants::C[168] = { + 0x67f815dfa2ded572ull, 0x571523b70a15847bull, 0xf6875a4d90d6ab81ull, 0x402bd1c3c54f9f4eull, + 0x9cfa455ce03a98eaull, 0x9a99b26699d2c503ull, 0x8a53bbf2b4960266ull, 0x31a2db881a1456b5ull, + 0xdb0e199a5c5aa303ull, 0x1044c1870ab23f40ull, 0x1d959e848019051cull, 0xdccde75eadeb336full, + 0x416bbf029213ba10ull, 0xd027bbf7156578dcull, 0x5078aa3739812c0aull, 0xd3910041d2bf1a3full, + 0x907eccf60d5a2d42ull, 0xce97c0929c9f62ddull, 0xac442bc70ba75c18ull, 0x23fcc663d665dfd1ull, + 0x1ab8e09e036c6e97ull, 0xa8ec6c447e450521ull, 0xfa618e5dbb03f1eeull, 0x97818394b29796fdull, + 0x2f3003db37858e4aull, 0x956a9ffb2d8d672aull, 0x6c69b8f88173fe8aull, 0x14427fc04672c78aull, + 0xc45ec7bd8f15f4c5ull, 0x80bb118fa76f4475ull, 0xbc88e4aeb775de52ull, 0xf4a3a6981e00b882ull, + 0x1563a3a9338ff48eull, 0x89f9b7d524565faaull, 0xfde05a7c20edf1b6ull, 0x362c42065ae9ca36ull, + 0x3d98fe4e433529ceull, 0xa74b9a7374f93a53ull, 0x86814e6f591ff5d0ull, 0x9f5ad8af81ad9d0eull, + 0x6a6234ee670605a7ull, 0x2717b96ebe280b8bull, 0x3f1080c626077447ull, 0x7b487ec66f7ea0e0ull, + 0xc0a4f84aa50a550dull, 0x9ef18e979fe7e391ull, 0xd48d605081727686ull, 0x62b0e5f3415a9e7eull, + 0x7a205440ec1f9ffcull, 0x84c9f4ce001ae4e3ull, 0xd895fa9df594d74full, 0xa554c324117e2e55ull, + 0x286efebd2872df5bull, 0xb2c4a50fe27ff578ull, 0x2ed349eeef7c8905ull, 0x7f5928eb85937e44ull, + 0x4a3124b337695f70ull, 0x65e4d61df128865eull, 0xe720b95104771bc7ull, 0x8a87d423e843fe74ull, + 0xf2947692a3e8297dull, 0xc1d9309b097acbddull, 0xe01bdc5bfb301b1dull, 0xbf829cf24f4924daull, + 0xffbf70b431bae7a4ull, 0x48bcf8de0544320dull, 0x39d3bb5332fcae3bull, 0xa08b29e0c1c39f45ull, + 0x0f09aef7fd05c9e5ull, 0x34f1904212347094ull, 0x95ed44e301b771a2ull, 0x4a982f4f368e3be9ull, + 0x15f66ca0631d4088ull, 0xffaf52874b44c147ull, 0x30c60ae2f14abb7eull, 0xe68c6eccc5b67046ull, + 0x00ca4fbd56a4d5a4ull, 0xae183ec84b849ddaull, 0xadd1643045ce5773ull, 0x67255c1468cea6e8ull, + 0x16e10ecbf28cdaa3ull, 0x9a99949a5806e933ull, 0x7b846fc220b2601full, 0x1885d1a07facced1ull, + 0xd319dd8da15b5932ull, 0x46b4a5aac01c9a50ull, 0xba6b04e467633d9full, 0x7eee560bab19caf6ull, + 0x742128a9ea79b11full, 0xee51363b35f7bde9ull, 0x76d350755aac571dull, 0x01707da3fec2463aull, + 0x42d8a498afc135f7ull, 0x79676b9e20eced78ull, 0xa8db3aea15638341ull, 0x832c83324d3bc3faull, + 0xf347271c1f3b40a7ull, 0x9a762db734f04059ull, 0xfd4f21d26c4e3ee7ull, 0xef5957dc398dfdb8ull, + 0xdaeb492b490c9b8dull, 0x0d70f36849d7a25bull, 0x84558d7ad0ae3b7dull, 0x658ef8e4f0e9a5f5ull, + 0x533b1036f4a2b8a0ull, 0x5aec3e759e07a80cull, 0x4f88e85692946891ull, 0x4cbcbaf8555cb05bull, + 0x7b9487f3993bbbe3ull, 0x5d1c6b72d6f4da75ull, 0x6db334dc28acae64ull, 0x71db28b850a5346cull, + 0x2a518d10f2e261f8ull, 0xfc75dd593364dbe3ull, 0xa23fce43f1bcac1cull, 0xb043e8023cd1bb67ull, + 0x75a12988ca5b0a33ull, 0x5c5316b44d19347full, 0x1e4d790ec3943b92ull, 0x3fafeeb6d7757479ull, + 0x21391abef7d4a8eaull, 0x5127234c097ef45cull, 0xd23c32ba5324a326ull, 0xadd5a66d4a17a344ull, + 0x08c9f2afa63e1db5ull, 0x563c6b91983d5983ull, 0x4d608672a17cf84cull, 0xf6c76e08cc3ee246ull, + 0x5e76bcb1b333982full, 0x2ae6c4efa566d62bull, 0x36d4c1bee8b6f406ull, 0x6321efbc1582ee74ull, + 0x69c953f40d4ec1fdull, 0x26585806c45a7da7ull, 0x16fae0061614c17eull, 0x3f9d63283daf907eull, + 0x0cd29b00e3f2c9d2ull, 0x300cd4b730ceaa5full, 0x9832e0f216512a74ull, 0x9af8cee3d830eb0dull, + 0x9279f1b57b9ec54bull, 0xd36886046ee651ffull, 0x316796e6574d239bull, 0x05750a17f3a6e6ccull, + 0xce6c3213d98176b1ull, 0x62a205f88452173cull, 0x47154778b3cb2bf4ull, 0x486a9323825446ffull, + 0x65655e4e0758df38ull, 0x8e5086fc897cfcf2ull, 0x86ca0bd0442e7031ull, 0x4e477830a20940f0ull, + 0x8338f7d139eea065ull, 0xbd3a2ce437e95ef7ull, 0x6ff8130126b29721ull, 0xe7de9fefd1ed44a3ull, + 0xd992257615dfa08bull, 0xbe42dc12f6f7853cull, 0x7eb027ab7ceca7d8ull, 0xdea83eaada7d8d53ull, + 0xd86902bd93ce25aaull, 0xf908731afd43f65aull, 0xa5194a17daef5fc0ull, 0x6a21fd4c33664d97ull, + 0x701541db3198b435ull, 0x9b54cdedbb0f1eeaull, 0x72409751a163d09aull, 0xe26f4791bf9d75f6ull +}; + +} // namespace detail + +} // namespace digestpp + +#endif \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/detail/constants/kupyna_constants.hpp b/ext/include/digestpp/algorithm/detail/constants/kupyna_constants.hpp new file mode 100644 index 0000000..e16b06b --- /dev/null +++ b/ext/include/digestpp/algorithm/detail/constants/kupyna_constants.hpp @@ -0,0 +1,557 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_PROVIDERS_KUPYNA_CONSTANTS_HPP +#define DIGESTPP_PROVIDERS_KUPYNA_CONSTANTS_HPP + +namespace digestpp +{ + +namespace detail +{ + +template +struct kupyna_constants +{ + static const uint64_t T[8][256]; + +}; + +template +const uint64_t kupyna_constants::T[8][256] = { + { + 0xa832a829d77f9aa8ull, 0x4352432297d41143ull, 0x5f3e5fc2df80615full, 0x061e063014121806ull, + 0x6bda6b7f670cb16bull, 0x75bc758f2356c975ull, 0x6cc16c477519ad6cull, 0x592059f2cb927959ull, + 0x71a871af3b4ad971ull, 0xdf84dfb6f8275bdfull, 0x87a1874c35b22687ull, 0x95fb95dc59cc6e95ull, + 0x174b17b872655c17ull, 0xf017f0d31aeae7f0ull, 0xd89fd88eea3247d8ull, 0x092d0948363f2409ull, + 0x6dc46d4f731ea96dull, 0xf318f3cb10e3ebf3ull, 0x1d691de84e53741dull, 0xcbc0cb16804b0bcbull, + 0xc9cac9068c4503c9ull, 0x4d644d52b3fe294dull, 0x2c9c2c7de8c4b02cull, 0xaf29af11c56a86afull, + 0x798079ef0b72f979ull, 0xe047e0537a9aa7e0ull, 0x97f197cc55c26697ull, 0xfd2efdbb34c9d3fdull, + 0x6fce6f5f7f10a16full, 0x4b7a4b62a7ec314bull, 0x454c451283c60945ull, 0x39dd39d596afe439ull, + 0x3ec63eed84baf83eull, 0xdd8edda6f42953ddull, 0xa315a371ed4eb6a3ull, 0x4f6e4f42bff0214full, + 0xb45eb4c99f2beab4ull, 0xb654b6d99325e2b6ull, 0x9ac89aa47be1529aull, 0x0e360e70242a380eull, + 0x1f631ff8425d7c1full, 0xbf79bf91a51ac6bfull, 0x154115a87e6b5415ull, 0xe142e15b7c9da3e1ull, + 0x49704972abe23949ull, 0xd2bdd2ded6046fd2ull, 0x93e593ec4dde7693ull, 0xc6f9c67eae683fc6ull, + 0x92e092e44bd97292ull, 0x72a772b73143d572ull, 0x9edc9e8463fd429eull, 0x61f8612f5b3a9961ull, + 0xd1b2d1c6dc0d63d1ull, 0x63f2633f57349163ull, 0xfa35fa8326dccffaull, 0xee71ee235eb09feeull, + 0xf403f4f302f6f7f4ull, 0x197d19c8564f6419ull, 0xd5a6d5e6c41173d5ull, 0xad23ad01c9648eadull, + 0x582558facd957d58ull, 0xa40ea449ff5baaa4ull, 0xbb6dbbb1bd06d6bbull, 0xa11fa161e140bea1ull, + 0xdc8bdcaef22e57dcull, 0xf21df2c316e4eff2ull, 0x83b5836c2dae3683ull, 0x37eb37a5b285dc37ull, + 0x4257422a91d31542ull, 0xe453e4736286b7e4ull, 0x7a8f7af7017bf57aull, 0x32fa328dac9ec832ull, + 0x9cd69c946ff34a9cull, 0xccdbcc2e925e17ccull, 0xab3dab31dd7696abull, 0x4a7f4a6aa1eb354aull, + 0x8f898f0c058a068full, 0x6ecb6e577917a56eull, 0x04140420181c1004ull, 0x27bb2725d2f59c27ull, + 0x2e962e6de4cab82eull, 0xe75ce76b688fbbe7ull, 0xe24de2437694afe2ull, 0x5a2f5aeac19b755aull, + 0x96f496c453c56296ull, 0x164e16b074625816ull, 0x23af2305cae98c23ull, 0x2b872b45fad1ac2bull, + 0xc2edc25eb6742fc2ull, 0x65ec650f43268965ull, 0x66e36617492f8566ull, 0x0f330f78222d3c0full, + 0xbc76bc89af13cabcull, 0xa937a921d1789ea9ull, 0x474647028fc80147ull, 0x415841329bda1941ull, + 0x34e434bdb88cd034ull, 0x4875487aade53d48ull, 0xfc2bfcb332ced7fcull, 0xb751b7d19522e6b7ull, + 0x6adf6a77610bb56aull, 0x88928834179f1a88ull, 0xa50ba541f95caea5ull, 0x530253a2f7a45153ull, + 0x86a4864433b52286ull, 0xf93af99b2cd5c3f9ull, 0x5b2a5be2c79c715bull, 0xdb90db96e03b4bdbull, + 0x38d838dd90a8e038ull, 0x7b8a7bff077cf17bull, 0xc3e8c356b0732bc3ull, 0x1e661ef0445a781eull, + 0x22aa220dccee8822ull, 0x33ff3385aa99cc33ull, 0x24b4243dd8fc9024ull, 0x2888285df0d8a028ull, + 0x36ee36adb482d836ull, 0xc7fcc776a86f3bc7ull, 0xb240b2f98b39f2b2ull, 0x3bd73bc59aa1ec3bull, + 0x8e8c8e04038d028eull, 0x77b6779f2f58c177ull, 0xba68bab9bb01d2baull, 0xf506f5fb04f1f3f5ull, + 0x144414a0786c5014ull, 0x9fd99f8c65fa469full, 0x0828084030382008ull, 0x551c5592e3b64955ull, + 0x9bcd9bac7de6569bull, 0x4c614c5ab5f92d4cull, 0xfe21fea33ec0dffeull, 0x60fd60275d3d9d60ull, + 0x5c315cdad5896d5cull, 0xda95da9ee63c4fdaull, 0x187818c050486018ull, 0x4643460a89cf0546ull, + 0xcddecd26945913cdull, 0x7d947dcf136ee97dull, 0x21a52115c6e78421ull, 0xb04ab0e98737fab0ull, + 0x3fc33fe582bdfc3full, 0x1b771bd85a416c1bull, 0x8997893c11981e89ull, 0xff24ffab38c7dbffull, + 0xeb60eb0b40ab8bebull, 0x84ae84543fbb2a84ull, 0x69d0696f6b02b969ull, 0x3ad23acd9ca6e83aull, + 0x9dd39d9c69f44e9dull, 0xd7acd7f6c81f7bd7ull, 0xd3b8d3d6d0036bd3ull, 0x70ad70a73d4ddd70ull, + 0x67e6671f4f288167ull, 0x405d403a9ddd1d40ull, 0xb55bb5c1992ceeb5ull, 0xde81debefe205fdeull, + 0x5d345dd2d38e695dull, 0x30f0309da090c030ull, 0x91ef91fc41d07e91ull, 0xb14fb1e18130feb1ull, + 0x788578e70d75fd78ull, 0x1155118866774411ull, 0x0105010806070401ull, 0xe556e57b6481b3e5ull, + 0x0000000000000000ull, 0x68d568676d05bd68ull, 0x98c298b477ef5a98ull, 0xa01aa069e747baa0ull, + 0xc5f6c566a46133c5ull, 0x020a02100c0e0802ull, 0xa604a659f355a2a6ull, 0x74b974872551cd74ull, + 0x2d992d75eec3b42dull, 0x0b270b583a312c0bull, 0xa210a279eb49b2a2ull, 0x76b37697295fc576ull, + 0xb345b3f18d3ef6b3ull, 0xbe7cbe99a31dc2beull, 0xced1ce3e9e501fceull, 0xbd73bd81a914cebdull, + 0xae2cae19c36d82aeull, 0xe96ae91b4ca583e9ull, 0x8a988a241b91128aull, 0x31f53195a697c431ull, + 0x1c6c1ce04854701cull, 0xec7bec3352be97ecull, 0xf112f1db1cede3f1ull, 0x99c799bc71e85e99ull, + 0x94fe94d45fcb6a94ull, 0xaa38aa39db7192aaull, 0xf609f6e30ef8fff6ull, 0x26be262dd4f29826ull, + 0x2f932f65e2cdbc2full, 0xef74ef2b58b79befull, 0xe86fe8134aa287e8ull, 0x8c868c140f830a8cull, + 0x35e135b5be8bd435ull, 0x030f03180a090c03ull, 0xd4a3d4eec21677d4ull, 0x7f9e7fdf1f60e17full, + 0xfb30fb8b20dbcbfbull, 0x051105281e1b1405ull, 0xc1e2c146bc7d23c1ull, 0x5e3b5ecad987655eull, + 0x90ea90f447d77a90ull, 0x20a0201dc0e08020ull, 0x3dc93df58eb3f43dull, 0x82b082642ba93282ull, + 0xf70cf7eb08fffbf7ull, 0xea65ea0346ac8feaull, 0x0a220a503c36280aull, 0x0d390d682e23340dull, + 0x7e9b7ed71967e57eull, 0xf83ff8932ad2c7f8ull, 0x500d50bafdad5d50ull, 0x1a721ad05c46681aull, + 0xc4f3c46ea26637c4ull, 0x071b073812151c07ull, 0x57165782efb84157ull, 0xb862b8a9b70fdab8ull, + 0x3ccc3cfd88b4f03cull, 0x62f7623751339562ull, 0xe348e34b7093abe3ull, 0xc8cfc80e8a4207c8ull, + 0xac26ac09cf638aacull, 0x520752aaf1a35552ull, 0x64e9640745218d64ull, 0x1050108060704010ull, + 0xd0b7d0ceda0a67d0ull, 0xd99ad986ec3543d9ull, 0x135f13986a794c13ull, 0x0c3c0c602824300cull, + 0x125a12906c7e4812ull, 0x298d2955f6dfa429ull, 0x510851b2fbaa5951ull, 0xb967b9a1b108deb9ull, + 0xcfd4cf3698571bcfull, 0xd6a9d6fece187fd6ull, 0x73a273bf3744d173ull, 0x8d838d1c09840e8dull, + 0x81bf817c21a03e81ull, 0x5419549ae5b14d54ull, 0xc0e7c04eba7a27c0ull, 0xed7eed3b54b993edull, + 0x4e6b4e4ab9f7254eull, 0x4449441a85c10d44ull, 0xa701a751f552a6a7ull, 0x2a822a4dfcd6a82aull, + 0x85ab855c39bc2e85ull, 0x25b12535defb9425ull, 0xe659e6636e88bfe6ull, 0xcac5ca1e864c0fcaull, + 0x7c917cc71569ed7cull, 0x8b9d8b2c1d96168bull, 0x5613568ae9bf4556ull, 0x80ba807427a73a80ull + }, + { + 0xd1ce3e9e501fceceull, 0x6dbbb1bd06d6bbbbull, 0x60eb0b40ab8bebebull, 0xe092e44bd9729292ull, + 0x65ea0346ac8feaeaull, 0xc0cb16804b0bcbcbull, 0x5f13986a794c1313ull, 0xe2c146bc7d23c1c1ull, + 0x6ae91b4ca583e9e9ull, 0xd23acd9ca6e83a3aull, 0xa9d6fece187fd6d6ull, 0x40b2f98b39f2b2b2ull, + 0xbdd2ded6046fd2d2ull, 0xea90f447d77a9090ull, 0x4b17b872655c1717ull, 0x3ff8932ad2c7f8f8ull, + 0x57422a91d3154242ull, 0x4115a87e6b541515ull, 0x13568ae9bf455656ull, 0x5eb4c99f2beab4b4ull, + 0xec650f4326896565ull, 0x6c1ce04854701c1cull, 0x928834179f1a8888ull, 0x52432297d4114343ull, + 0xf6c566a46133c5c5ull, 0x315cdad5896d5c5cull, 0xee36adb482d83636ull, 0x68bab9bb01d2babaull, + 0x06f5fb04f1f3f5f5ull, 0x165782efb8415757ull, 0xe6671f4f28816767ull, 0x838d1c09840e8d8dull, + 0xf53195a697c43131ull, 0x09f6e30ef8fff6f6ull, 0xe9640745218d6464ull, 0x2558facd957d5858ull, + 0xdc9e8463fd429e9eull, 0x03f4f302f6f7f4f4ull, 0xaa220dccee882222ull, 0x38aa39db7192aaaaull, + 0xbc758f2356c97575ull, 0x330f78222d3c0f0full, 0x0a02100c0e080202ull, 0x4fb1e18130feb1b1ull, + 0x84dfb6f8275bdfdfull, 0xc46d4f731ea96d6dull, 0xa273bf3744d17373ull, 0x644d52b3fe294d4dull, + 0x917cc71569ed7c7cull, 0xbe262dd4f2982626ull, 0x962e6de4cab82e2eull, 0x0cf7eb08fffbf7f7ull, + 0x2808403038200808ull, 0x345dd2d38e695d5dull, 0x49441a85c10d4444ull, 0xc63eed84baf83e3eull, + 0xd99f8c65fa469f9full, 0x4414a0786c501414ull, 0xcfc80e8a4207c8c8ull, 0x2cae19c36d82aeaeull, + 0x19549ae5b14d5454ull, 0x5010806070401010ull, 0x9fd88eea3247d8d8ull, 0x76bc89af13cabcbcull, + 0x721ad05c46681a1aull, 0xda6b7f670cb16b6bull, 0xd0696f6b02b96969ull, 0x18f3cb10e3ebf3f3ull, + 0x73bd81a914cebdbdull, 0xff3385aa99cc3333ull, 0x3dab31dd7696ababull, 0x35fa8326dccffafaull, + 0xb2d1c6dc0d63d1d1ull, 0xcd9bac7de6569b9bull, 0xd568676d05bd6868ull, 0x6b4e4ab9f7254e4eull, + 0x4e16b07462581616ull, 0xfb95dc59cc6e9595ull, 0xef91fc41d07e9191ull, 0x71ee235eb09feeeeull, + 0x614c5ab5f92d4c4cull, 0xf2633f5734916363ull, 0x8c8e04038d028e8eull, 0x2a5be2c79c715b5bull, + 0xdbcc2e925e17ccccull, 0xcc3cfd88b4f03c3cull, 0x7d19c8564f641919ull, 0x1fa161e140bea1a1ull, + 0xbf817c21a03e8181ull, 0x704972abe2394949ull, 0x8a7bff077cf17b7bull, 0x9ad986ec3543d9d9ull, + 0xce6f5f7f10a16f6full, 0xeb37a5b285dc3737ull, 0xfd60275d3d9d6060ull, 0xc5ca1e864c0fcacaull, + 0x5ce76b688fbbe7e7ull, 0x872b45fad1ac2b2bull, 0x75487aade53d4848ull, 0x2efdbb34c9d3fdfdull, + 0xf496c453c5629696ull, 0x4c451283c6094545ull, 0x2bfcb332ced7fcfcull, 0x5841329bda194141ull, + 0x5a12906c7e481212ull, 0x390d682e23340d0dull, 0x8079ef0b72f97979ull, 0x56e57b6481b3e5e5ull, + 0x97893c11981e8989ull, 0x868c140f830a8c8cull, 0x48e34b7093abe3e3ull, 0xa0201dc0e0802020ull, + 0xf0309da090c03030ull, 0x8bdcaef22e57dcdcull, 0x51b7d19522e6b7b7ull, 0xc16c477519ad6c6cull, + 0x7f4a6aa1eb354a4aull, 0x5bb5c1992ceeb5b5ull, 0xc33fe582bdfc3f3full, 0xf197cc55c2669797ull, + 0xa3d4eec21677d4d4ull, 0xf762375133956262ull, 0x992d75eec3b42d2dull, 0x1e06301412180606ull, + 0x0ea449ff5baaa4a4ull, 0x0ba541f95caea5a5ull, 0xb5836c2dae368383ull, 0x3e5fc2df80615f5full, + 0x822a4dfcd6a82a2aull, 0x95da9ee63c4fdadaull, 0xcac9068c4503c9c9ull, 0x0000000000000000ull, + 0x9b7ed71967e57e7eull, 0x10a279eb49b2a2a2ull, 0x1c5592e3b6495555ull, 0x79bf91a51ac6bfbfull, + 0x5511886677441111ull, 0xa6d5e6c41173d5d5ull, 0xd69c946ff34a9c9cull, 0xd4cf3698571bcfcfull, + 0x360e70242a380e0eull, 0x220a503c36280a0aull, 0xc93df58eb3f43d3dull, 0x0851b2fbaa595151ull, + 0x947dcf136ee97d7dull, 0xe593ec4dde769393ull, 0x771bd85a416c1b1bull, 0x21fea33ec0dffefeull, + 0xf3c46ea26637c4c4ull, 0x4647028fc8014747ull, 0x2d0948363f240909ull, 0xa4864433b5228686ull, + 0x270b583a312c0b0bull, 0x898f0c058a068f8full, 0xd39d9c69f44e9d9dull, 0xdf6a77610bb56a6aull, + 0x1b073812151c0707ull, 0x67b9a1b108deb9b9ull, 0x4ab0e98737fab0b0ull, 0xc298b477ef5a9898ull, + 0x7818c05048601818ull, 0xfa328dac9ec83232ull, 0xa871af3b4ad97171ull, 0x7a4b62a7ec314b4bull, + 0x74ef2b58b79befefull, 0xd73bc59aa1ec3b3bull, 0xad70a73d4ddd7070ull, 0x1aa069e747baa0a0ull, + 0x53e4736286b7e4e4ull, 0x5d403a9ddd1d4040ull, 0x24ffab38c7dbffffull, 0xe8c356b0732bc3c3ull, + 0x37a921d1789ea9a9ull, 0x59e6636e88bfe6e6ull, 0x8578e70d75fd7878ull, 0x3af99b2cd5c3f9f9ull, + 0x9d8b2c1d96168b8bull, 0x43460a89cf054646ull, 0xba807427a73a8080ull, 0x661ef0445a781e1eull, + 0xd838dd90a8e03838ull, 0x42e15b7c9da3e1e1ull, 0x62b8a9b70fdab8b8ull, 0x32a829d77f9aa8a8ull, + 0x47e0537a9aa7e0e0ull, 0x3c0c602824300c0cull, 0xaf2305cae98c2323ull, 0xb37697295fc57676ull, + 0x691de84e53741d1dull, 0xb12535defb942525ull, 0xb4243dd8fc902424ull, 0x1105281e1b140505ull, + 0x12f1db1cede3f1f1ull, 0xcb6e577917a56e6eull, 0xfe94d45fcb6a9494ull, 0x88285df0d8a02828ull, + 0xc89aa47be1529a9aull, 0xae84543fbb2a8484ull, 0x6fe8134aa287e8e8ull, 0x15a371ed4eb6a3a3ull, + 0x6e4f42bff0214f4full, 0xb6779f2f58c17777ull, 0xb8d3d6d0036bd3d3ull, 0xab855c39bc2e8585ull, + 0x4de2437694afe2e2ull, 0x0752aaf1a3555252ull, 0x1df2c316e4eff2f2ull, 0xb082642ba9328282ull, + 0x0d50bafdad5d5050ull, 0x8f7af7017bf57a7aull, 0x932f65e2cdbc2f2full, 0xb974872551cd7474ull, + 0x0253a2f7a4515353ull, 0x45b3f18d3ef6b3b3ull, 0xf8612f5b3a996161ull, 0x29af11c56a86afafull, + 0xdd39d596afe43939ull, 0xe135b5be8bd43535ull, 0x81debefe205fdedeull, 0xdecd26945913cdcdull, + 0x631ff8425d7c1f1full, 0xc799bc71e85e9999ull, 0x26ac09cf638aacacull, 0x23ad01c9648eadadull, + 0xa772b73143d57272ull, 0x9c2c7de8c4b02c2cull, 0x8edda6f42953ddddull, 0xb7d0ceda0a67d0d0ull, + 0xa1874c35b2268787ull, 0x7cbe99a31dc2bebeull, 0x3b5ecad987655e5eull, 0x04a659f355a2a6a6ull, + 0x7bec3352be97ececull, 0x140420181c100404ull, 0xf9c67eae683fc6c6ull, 0x0f03180a090c0303ull, + 0xe434bdb88cd03434ull, 0x30fb8b20dbcbfbfbull, 0x90db96e03b4bdbdbull, 0x2059f2cb92795959ull, + 0x54b6d99325e2b6b6ull, 0xedc25eb6742fc2c2ull, 0x0501080607040101ull, 0x17f0d31aeae7f0f0ull, + 0x2f5aeac19b755a5aull, 0x7eed3b54b993ededull, 0x01a751f552a6a7a7ull, 0xe36617492f856666ull, + 0xa52115c6e7842121ull, 0x9e7fdf1f60e17f7full, 0x988a241b91128a8aull, 0xbb2725d2f59c2727ull, + 0xfcc776a86f3bc7c7ull, 0xe7c04eba7a27c0c0ull, 0x8d2955f6dfa42929ull, 0xacd7f6c81f7bd7d7ull + }, + { + 0x93ec4dde769393e5ull, 0xd986ec3543d9d99aull, 0x9aa47be1529a9ac8ull, 0xb5c1992ceeb5b55bull, + 0x98b477ef5a9898c2ull, 0x220dccee882222aaull, 0x451283c60945454cull, 0xfcb332ced7fcfc2bull, + 0xbab9bb01d2baba68ull, 0x6a77610bb56a6adfull, 0xdfb6f8275bdfdf84ull, 0x02100c0e0802020aull, + 0x9f8c65fa469f9fd9ull, 0xdcaef22e57dcdc8bull, 0x51b2fbaa59515108ull, 0x59f2cb9279595920ull, + 0x4a6aa1eb354a4a7full, 0x17b872655c17174bull, 0x2b45fad1ac2b2b87ull, 0xc25eb6742fc2c2edull, + 0x94d45fcb6a9494feull, 0xf4f302f6f7f4f403ull, 0xbbb1bd06d6bbbb6dull, 0xa371ed4eb6a3a315ull, + 0x62375133956262f7ull, 0xe4736286b7e4e453ull, 0x71af3b4ad97171a8ull, 0xd4eec21677d4d4a3ull, + 0xcd26945913cdcddeull, 0x70a73d4ddd7070adull, 0x16b074625816164eull, 0xe15b7c9da3e1e142ull, + 0x4972abe239494970ull, 0x3cfd88b4f03c3cccull, 0xc04eba7a27c0c0e7ull, 0xd88eea3247d8d89full, + 0x5cdad5896d5c5c31ull, 0x9bac7de6569b9bcdull, 0xad01c9648eadad23ull, 0x855c39bc2e8585abull, + 0x53a2f7a451535302ull, 0xa161e140bea1a11full, 0x7af7017bf57a7a8full, 0xc80e8a4207c8c8cfull, + 0x2d75eec3b42d2d99ull, 0xe0537a9aa7e0e047ull, 0xd1c6dc0d63d1d1b2ull, 0x72b73143d57272a7ull, + 0xa659f355a2a6a604ull, 0x2c7de8c4b02c2c9cull, 0xc46ea26637c4c4f3ull, 0xe34b7093abe3e348ull, + 0x7697295fc57676b3ull, 0x78e70d75fd787885ull, 0xb7d19522e6b7b751ull, 0xb4c99f2beab4b45eull, + 0x0948363f2409092dull, 0x3bc59aa1ec3b3bd7ull, 0x0e70242a380e0e36ull, 0x41329bda19414158ull, + 0x4c5ab5f92d4c4c61ull, 0xdebefe205fdede81ull, 0xb2f98b39f2b2b240ull, 0x90f447d77a9090eaull, + 0x2535defb942525b1ull, 0xa541f95caea5a50bull, 0xd7f6c81f7bd7d7acull, 0x03180a090c03030full, + 0x1188667744111155ull, 0x0000000000000000ull, 0xc356b0732bc3c3e8ull, 0x2e6de4cab82e2e96ull, + 0x92e44bd9729292e0ull, 0xef2b58b79befef74ull, 0x4e4ab9f7254e4e6bull, 0x12906c7e4812125aull, + 0x9d9c69f44e9d9dd3ull, 0x7dcf136ee97d7d94ull, 0xcb16804b0bcbcbc0ull, 0x35b5be8bd43535e1ull, + 0x1080607040101050ull, 0xd5e6c41173d5d5a6ull, 0x4f42bff0214f4f6eull, 0x9e8463fd429e9edcull, + 0x4d52b3fe294d4d64ull, 0xa921d1789ea9a937ull, 0x5592e3b64955551cull, 0xc67eae683fc6c6f9ull, + 0xd0ceda0a67d0d0b7ull, 0x7bff077cf17b7b8aull, 0x18c0504860181878ull, 0x97cc55c2669797f1ull, + 0xd3d6d0036bd3d3b8ull, 0x36adb482d83636eeull, 0xe6636e88bfe6e659ull, 0x487aade53d484875ull, + 0x568ae9bf45565613ull, 0x817c21a03e8181bfull, 0x8f0c058a068f8f89ull, 0x779f2f58c17777b6ull, + 0xcc2e925e17ccccdbull, 0x9c946ff34a9c9cd6ull, 0xb9a1b108deb9b967ull, 0xe2437694afe2e24dull, + 0xac09cf638aacac26ull, 0xb8a9b70fdab8b862ull, 0x2f65e2cdbc2f2f93ull, 0x15a87e6b54151541ull, + 0xa449ff5baaa4a40eull, 0x7cc71569ed7c7c91ull, 0xda9ee63c4fdada95ull, 0x38dd90a8e03838d8ull, + 0x1ef0445a781e1e66ull, 0x0b583a312c0b0b27ull, 0x05281e1b14050511ull, 0xd6fece187fd6d6a9ull, + 0x14a0786c50141444ull, 0x6e577917a56e6ecbull, 0x6c477519ad6c6cc1ull, 0x7ed71967e57e7e9bull, + 0x6617492f856666e3ull, 0xfdbb34c9d3fdfd2eull, 0xb1e18130feb1b14full, 0xe57b6481b3e5e556ull, + 0x60275d3d9d6060fdull, 0xaf11c56a86afaf29ull, 0x5ecad987655e5e3bull, 0x3385aa99cc3333ffull, + 0x874c35b2268787a1ull, 0xc9068c4503c9c9caull, 0xf0d31aeae7f0f017ull, 0x5dd2d38e695d5d34ull, + 0x6d4f731ea96d6dc4ull, 0x3fe582bdfc3f3fc3ull, 0x8834179f1a888892ull, 0x8d1c09840e8d8d83ull, + 0xc776a86f3bc7c7fcull, 0xf7eb08fffbf7f70cull, 0x1de84e53741d1d69ull, 0xe91b4ca583e9e96aull, + 0xec3352be97ecec7bull, 0xed3b54b993eded7eull, 0x807427a73a8080baull, 0x2955f6dfa429298dull, + 0x2725d2f59c2727bbull, 0xcf3698571bcfcfd4ull, 0x99bc71e85e9999c7ull, 0xa829d77f9aa8a832ull, + 0x50bafdad5d50500dull, 0x0f78222d3c0f0f33ull, 0x37a5b285dc3737ebull, 0x243dd8fc902424b4ull, + 0x285df0d8a0282888ull, 0x309da090c03030f0ull, 0x95dc59cc6e9595fbull, 0xd2ded6046fd2d2bdull, + 0x3eed84baf83e3ec6ull, 0x5be2c79c715b5b2aull, 0x403a9ddd1d40405dull, 0x836c2dae368383b5ull, + 0xb3f18d3ef6b3b345ull, 0x696f6b02b96969d0ull, 0x5782efb841575716ull, 0x1ff8425d7c1f1f63ull, + 0x073812151c07071bull, 0x1ce04854701c1c6cull, 0x8a241b91128a8a98ull, 0xbc89af13cabcbc76ull, + 0x201dc0e0802020a0ull, 0xeb0b40ab8bebeb60ull, 0xce3e9e501fceced1ull, 0x8e04038d028e8e8cull, + 0xab31dd7696abab3dull, 0xee235eb09feeee71ull, 0x3195a697c43131f5ull, 0xa279eb49b2a2a210ull, + 0x73bf3744d17373a2ull, 0xf99b2cd5c3f9f93aull, 0xca1e864c0fcacac5ull, 0x3acd9ca6e83a3ad2ull, + 0x1ad05c46681a1a72ull, 0xfb8b20dbcbfbfb30ull, 0x0d682e23340d0d39ull, 0xc146bc7d23c1c1e2ull, + 0xfea33ec0dffefe21ull, 0xfa8326dccffafa35ull, 0xf2c316e4eff2f21dull, 0x6f5f7f10a16f6fceull, + 0xbd81a914cebdbd73ull, 0x96c453c5629696f4ull, 0xdda6f42953dddd8eull, 0x432297d411434352ull, + 0x52aaf1a355525207ull, 0xb6d99325e2b6b654ull, 0x0840303820080828ull, 0xf3cb10e3ebf3f318ull, + 0xae19c36d82aeae2cull, 0xbe99a31dc2bebe7cull, 0x19c8564f6419197dull, 0x893c11981e898997ull, + 0x328dac9ec83232faull, 0x262dd4f2982626beull, 0xb0e98737fab0b04aull, 0xea0346ac8feaea65ull, + 0x4b62a7ec314b4b7aull, 0x640745218d6464e9ull, 0x84543fbb2a8484aeull, 0x82642ba9328282b0ull, + 0x6b7f670cb16b6bdaull, 0xf5fb04f1f3f5f506ull, 0x79ef0b72f9797980ull, 0xbf91a51ac6bfbf79ull, + 0x0108060704010105ull, 0x5fc2df80615f5f3eull, 0x758f2356c97575bcull, 0x633f5734916363f2ull, + 0x1bd85a416c1b1b77ull, 0x2305cae98c2323afull, 0x3df58eb3f43d3dc9ull, 0x68676d05bd6868d5ull, + 0x2a4dfcd6a82a2a82ull, 0x650f4326896565ecull, 0xe8134aa287e8e86full, 0x91fc41d07e9191efull, + 0xf6e30ef8fff6f609ull, 0xffab38c7dbffff24ull, 0x13986a794c13135full, 0x58facd957d585825ull, + 0xf1db1cede3f1f112ull, 0x47028fc801474746ull, 0x0a503c36280a0a22ull, 0x7fdf1f60e17f7f9eull, + 0xc566a46133c5c5f6ull, 0xa751f552a6a7a701ull, 0xe76b688fbbe7e75cull, 0x612f5b3a996161f8ull, + 0x5aeac19b755a5a2full, 0x063014121806061eull, 0x460a89cf05464643ull, 0x441a85c10d444449ull, + 0x422a91d315424257ull, 0x0420181c10040414ull, 0xa069e747baa0a01aull, 0xdb96e03b4bdbdb90ull, + 0x39d596afe43939ddull, 0x864433b5228686a4ull, 0x549ae5b14d545419ull, 0xaa39db7192aaaa38ull, + 0x8c140f830a8c8c86ull, 0x34bdb88cd03434e4ull, 0x2115c6e7842121a5ull, 0x8b2c1d96168b8b9dull, + 0xf8932ad2c7f8f83full, 0x0c602824300c0c3cull, 0x74872551cd7474b9ull, 0x671f4f28816767e6ull + }, + { + 0x676d05bd6868d568ull, 0x1c09840e8d8d838dull, 0x1e864c0fcacac5caull, 0x52b3fe294d4d644dull, + 0xbf3744d17373a273ull, 0x62a7ec314b4b7a4bull, 0x4ab9f7254e4e6b4eull, 0x4dfcd6a82a2a822aull, + 0xeec21677d4d4a3d4ull, 0xaaf1a35552520752ull, 0x2dd4f2982626be26ull, 0xf18d3ef6b3b345b3ull, + 0x9ae5b14d54541954ull, 0xf0445a781e1e661eull, 0xc8564f6419197d19ull, 0xf8425d7c1f1f631full, + 0x0dccee882222aa22ull, 0x180a090c03030f03ull, 0x0a89cf0546464346ull, 0xf58eb3f43d3dc93dull, + 0x75eec3b42d2d992dull, 0x6aa1eb354a4a7f4aull, 0xa2f7a45153530253ull, 0x6c2dae368383b583ull, + 0x986a794c13135f13ull, 0x241b91128a8a988aull, 0xd19522e6b7b751b7ull, 0xe6c41173d5d5a6d5ull, + 0x35defb942525b125ull, 0xef0b72f979798079ull, 0xfb04f1f3f5f506f5ull, 0x81a914cebdbd73bdull, + 0xfacd957d58582558ull, 0x65e2cdbc2f2f932full, 0x682e23340d0d390dull, 0x100c0e0802020a02ull, + 0x3b54b993eded7eedull, 0xb2fbaa5951510851ull, 0x8463fd429e9edc9eull, 0x8866774411115511ull, + 0xc316e4eff2f21df2ull, 0xed84baf83e3ec63eull, 0x92e3b64955551c55ull, 0xcad987655e5e3b5eull, + 0xc6dc0d63d1d1b2d1ull, 0xb074625816164e16ull, 0xfd88b4f03c3ccc3cull, 0x17492f856666e366ull, + 0xa73d4ddd7070ad70ull, 0xd2d38e695d5d345dull, 0xcb10e3ebf3f318f3ull, 0x1283c60945454c45ull, + 0x3a9ddd1d40405d40ull, 0x2e925e17ccccdbccull, 0x134aa287e8e86fe8ull, 0xd45fcb6a9494fe94ull, + 0x8ae9bf4556561356ull, 0x4030382008082808ull, 0x3e9e501fceced1ceull, 0xd05c46681a1a721aull, + 0xcd9ca6e83a3ad23aull, 0xded6046fd2d2bdd2ull, 0x5b7c9da3e1e142e1ull, 0xb6f8275bdfdf84dfull, + 0xc1992ceeb5b55bb5ull, 0xdd90a8e03838d838ull, 0x577917a56e6ecb6eull, 0x70242a380e0e360eull, + 0x7b6481b3e5e556e5ull, 0xf302f6f7f4f403f4ull, 0x9b2cd5c3f9f93af9ull, 0x4433b5228686a486ull, + 0x1b4ca583e9e96ae9ull, 0x42bff0214f4f6e4full, 0xfece187fd6d6a9d6ull, 0x5c39bc2e8585ab85ull, + 0x05cae98c2323af23ull, 0x3698571bcfcfd4cfull, 0x8dac9ec83232fa32ull, 0xbc71e85e9999c799ull, + 0x95a697c43131f531ull, 0xa0786c5014144414ull, 0x19c36d82aeae2caeull, 0x235eb09feeee71eeull, + 0x0e8a4207c8c8cfc8ull, 0x7aade53d48487548ull, 0xd6d0036bd3d3b8d3ull, 0x9da090c03030f030ull, + 0x61e140bea1a11fa1ull, 0xe44bd9729292e092ull, 0x329bda1941415841ull, 0xe18130feb1b14fb1ull, + 0xc050486018187818ull, 0x6ea26637c4c4f3c4ull, 0x7de8c4b02c2c9c2cull, 0xaf3b4ad97171a871ull, + 0xb73143d57272a772ull, 0x1a85c10d44444944ull, 0xa87e6b5415154115ull, 0xbb34c9d3fdfd2efdull, + 0xa5b285dc3737eb37ull, 0x99a31dc2bebe7cbeull, 0xc2df80615f5f3e5full, 0x39db7192aaaa38aaull, + 0xac7de6569b9bcd9bull, 0x34179f1a88889288ull, 0x8eea3247d8d89fd8ull, 0x31dd7696abab3dabull, + 0x3c11981e89899789ull, 0x946ff34a9c9cd69cull, 0x8326dccffafa35faull, 0x275d3d9d6060fd60ull, + 0x0346ac8feaea65eaull, 0x89af13cabcbc76bcull, 0x375133956262f762ull, 0x602824300c0c3c0cull, + 0x3dd8fc902424b424ull, 0x59f355a2a6a604a6ull, 0x29d77f9aa8a832a8ull, 0x3352be97ecec7becull, + 0x1f4f28816767e667ull, 0x1dc0e0802020a020ull, 0x96e03b4bdbdb90dbull, 0xc71569ed7c7c917cull, + 0x5df0d8a028288828ull, 0xa6f42953dddd8eddull, 0x09cf638aacac26acull, 0xe2c79c715b5b2a5bull, + 0xbdb88cd03434e434ull, 0xd71967e57e7e9b7eull, 0x8060704010105010ull, 0xdb1cede3f1f112f1ull, + 0xff077cf17b7b8a7bull, 0x0c058a068f8f898full, 0x3f5734916363f263ull, 0x69e747baa0a01aa0ull, + 0x281e1b1405051105ull, 0xa47be1529a9ac89aull, 0x2297d41143435243ull, 0x9f2f58c17777b677ull, + 0x15c6e7842121a521ull, 0x91a51ac6bfbf79bfull, 0x25d2f59c2727bb27ull, 0x48363f2409092d09ull, + 0x56b0732bc3c3e8c3ull, 0x8c65fa469f9fd99full, 0xd99325e2b6b654b6ull, 0xf6c81f7bd7d7acd7ull, + 0x55f6dfa429298d29ull, 0x5eb6742fc2c2edc2ull, 0x0b40ab8bebeb60ebull, 0x4eba7a27c0c0e7c0ull, + 0x49ff5baaa4a40ea4ull, 0x2c1d96168b8b9d8bull, 0x140f830a8c8c868cull, 0xe84e53741d1d691dull, + 0x8b20dbcbfbfb30fbull, 0xab38c7dbffff24ffull, 0x46bc7d23c1c1e2c1ull, 0xf98b39f2b2b240b2ull, + 0xcc55c2669797f197ull, 0x6de4cab82e2e962eull, 0x932ad2c7f8f83ff8ull, 0x0f4326896565ec65ull, + 0xe30ef8fff6f609f6ull, 0x8f2356c97575bc75ull, 0x3812151c07071b07ull, 0x20181c1004041404ull, + 0x72abe23949497049ull, 0x85aa99cc3333ff33ull, 0x736286b7e4e453e4ull, 0x86ec3543d9d99ad9ull, + 0xa1b108deb9b967b9ull, 0xceda0a67d0d0b7d0ull, 0x2a91d31542425742ull, 0x76a86f3bc7c7fcc7ull, + 0x477519ad6c6cc16cull, 0xf447d77a9090ea90ull, 0x0000000000000000ull, 0x04038d028e8e8c8eull, + 0x5f7f10a16f6fce6full, 0xbafdad5d50500d50ull, 0x0806070401010501ull, 0x66a46133c5c5f6c5ull, + 0x9ee63c4fdada95daull, 0x028fc80147474647ull, 0xe582bdfc3f3fc33full, 0x26945913cdcddecdull, + 0x6f6b02b96969d069ull, 0x79eb49b2a2a210a2ull, 0x437694afe2e24de2ull, 0xf7017bf57a7a8f7aull, + 0x51f552a6a7a701a7ull, 0x7eae683fc6c6f9c6ull, 0xec4dde769393e593ull, 0x78222d3c0f0f330full, + 0x503c36280a0a220aull, 0x3014121806061e06ull, 0x636e88bfe6e659e6ull, 0x45fad1ac2b2b872bull, + 0xc453c5629696f496ull, 0x71ed4eb6a3a315a3ull, 0xe04854701c1c6c1cull, 0x11c56a86afaf29afull, + 0x77610bb56a6adf6aull, 0x906c7e4812125a12ull, 0x543fbb2a8484ae84ull, 0xd596afe43939dd39ull, + 0x6b688fbbe7e75ce7ull, 0xe98737fab0b04ab0ull, 0x642ba9328282b082ull, 0xeb08fffbf7f70cf7ull, + 0xa33ec0dffefe21feull, 0x9c69f44e9d9dd39dull, 0x4c35b2268787a187ull, 0xdad5896d5c5c315cull, + 0x7c21a03e8181bf81ull, 0xb5be8bd43535e135ull, 0xbefe205fdede81deull, 0xc99f2beab4b45eb4ull, + 0x41f95caea5a50ba5ull, 0xb332ced7fcfc2bfcull, 0x7427a73a8080ba80ull, 0x2b58b79befef74efull, + 0x16804b0bcbcbc0cbull, 0xb1bd06d6bbbb6dbbull, 0x7f670cb16b6bda6bull, 0x97295fc57676b376ull, + 0xb9bb01d2baba68baull, 0xeac19b755a5a2f5aull, 0xcf136ee97d7d947dull, 0xe70d75fd78788578ull, + 0x583a312c0b0b270bull, 0xdc59cc6e9595fb95ull, 0x4b7093abe3e348e3ull, 0x01c9648eadad23adull, + 0x872551cd7474b974ull, 0xb477ef5a9898c298ull, 0xc59aa1ec3b3bd73bull, 0xadb482d83636ee36ull, + 0x0745218d6464e964ull, 0x4f731ea96d6dc46dull, 0xaef22e57dcdc8bdcull, 0xd31aeae7f0f017f0ull, + 0xf2cb927959592059ull, 0x21d1789ea9a937a9ull, 0x5ab5f92d4c4c614cull, 0xb872655c17174b17ull, + 0xdf1f60e17f7f9e7full, 0xfc41d07e9191ef91ull, 0xa9b70fdab8b862b8ull, 0x068c4503c9c9cac9ull, + 0x82efb84157571657ull, 0xd85a416c1b1b771bull, 0x537a9aa7e0e047e0ull, 0x2f5b3a996161f861ull + }, + { + 0xd77f9aa8a832a829ull, 0x97d4114343524322ull, 0xdf80615f5f3e5fc2ull, 0x14121806061e0630ull, + 0x670cb16b6bda6b7full, 0x2356c97575bc758full, 0x7519ad6c6cc16c47ull, 0xcb927959592059f2ull, + 0x3b4ad97171a871afull, 0xf8275bdfdf84dfb6ull, 0x35b2268787a1874cull, 0x59cc6e9595fb95dcull, + 0x72655c17174b17b8ull, 0x1aeae7f0f017f0d3ull, 0xea3247d8d89fd88eull, 0x363f2409092d0948ull, + 0x731ea96d6dc46d4full, 0x10e3ebf3f318f3cbull, 0x4e53741d1d691de8ull, 0x804b0bcbcbc0cb16ull, + 0x8c4503c9c9cac906ull, 0xb3fe294d4d644d52ull, 0xe8c4b02c2c9c2c7dull, 0xc56a86afaf29af11ull, + 0x0b72f979798079efull, 0x7a9aa7e0e047e053ull, 0x55c2669797f197ccull, 0x34c9d3fdfd2efdbbull, + 0x7f10a16f6fce6f5full, 0xa7ec314b4b7a4b62ull, 0x83c60945454c4512ull, 0x96afe43939dd39d5ull, + 0x84baf83e3ec63eedull, 0xf42953dddd8edda6ull, 0xed4eb6a3a315a371ull, 0xbff0214f4f6e4f42ull, + 0x9f2beab4b45eb4c9ull, 0x9325e2b6b654b6d9ull, 0x7be1529a9ac89aa4ull, 0x242a380e0e360e70ull, + 0x425d7c1f1f631ff8ull, 0xa51ac6bfbf79bf91ull, 0x7e6b5415154115a8ull, 0x7c9da3e1e142e15bull, + 0xabe2394949704972ull, 0xd6046fd2d2bdd2deull, 0x4dde769393e593ecull, 0xae683fc6c6f9c67eull, + 0x4bd9729292e092e4ull, 0x3143d57272a772b7ull, 0x63fd429e9edc9e84ull, 0x5b3a996161f8612full, + 0xdc0d63d1d1b2d1c6ull, 0x5734916363f2633full, 0x26dccffafa35fa83ull, 0x5eb09feeee71ee23ull, + 0x02f6f7f4f403f4f3ull, 0x564f6419197d19c8ull, 0xc41173d5d5a6d5e6ull, 0xc9648eadad23ad01ull, + 0xcd957d58582558faull, 0xff5baaa4a40ea449ull, 0xbd06d6bbbb6dbbb1ull, 0xe140bea1a11fa161ull, + 0xf22e57dcdc8bdcaeull, 0x16e4eff2f21df2c3ull, 0x2dae368383b5836cull, 0xb285dc3737eb37a5ull, + 0x91d315424257422aull, 0x6286b7e4e453e473ull, 0x017bf57a7a8f7af7ull, 0xac9ec83232fa328dull, + 0x6ff34a9c9cd69c94ull, 0x925e17ccccdbcc2eull, 0xdd7696abab3dab31ull, 0xa1eb354a4a7f4a6aull, + 0x058a068f8f898f0cull, 0x7917a56e6ecb6e57ull, 0x181c100404140420ull, 0xd2f59c2727bb2725ull, + 0xe4cab82e2e962e6dull, 0x688fbbe7e75ce76bull, 0x7694afe2e24de243ull, 0xc19b755a5a2f5aeaull, + 0x53c5629696f496c4ull, 0x74625816164e16b0ull, 0xcae98c2323af2305ull, 0xfad1ac2b2b872b45ull, + 0xb6742fc2c2edc25eull, 0x4326896565ec650full, 0x492f856666e36617ull, 0x222d3c0f0f330f78ull, + 0xaf13cabcbc76bc89ull, 0xd1789ea9a937a921ull, 0x8fc8014747464702ull, 0x9bda194141584132ull, + 0xb88cd03434e434bdull, 0xade53d484875487aull, 0x32ced7fcfc2bfcb3ull, 0x9522e6b7b751b7d1ull, + 0x610bb56a6adf6a77ull, 0x179f1a8888928834ull, 0xf95caea5a50ba541ull, 0xf7a45153530253a2ull, + 0x33b5228686a48644ull, 0x2cd5c3f9f93af99bull, 0xc79c715b5b2a5be2ull, 0xe03b4bdbdb90db96ull, + 0x90a8e03838d838ddull, 0x077cf17b7b8a7bffull, 0xb0732bc3c3e8c356ull, 0x445a781e1e661ef0ull, + 0xccee882222aa220dull, 0xaa99cc3333ff3385ull, 0xd8fc902424b4243dull, 0xf0d8a0282888285dull, + 0xb482d83636ee36adull, 0xa86f3bc7c7fcc776ull, 0x8b39f2b2b240b2f9ull, 0x9aa1ec3b3bd73bc5ull, + 0x038d028e8e8c8e04ull, 0x2f58c17777b6779full, 0xbb01d2baba68bab9ull, 0x04f1f3f5f506f5fbull, + 0x786c5014144414a0ull, 0x65fa469f9fd99f8cull, 0x3038200808280840ull, 0xe3b64955551c5592ull, + 0x7de6569b9bcd9bacull, 0xb5f92d4c4c614c5aull, 0x3ec0dffefe21fea3ull, 0x5d3d9d6060fd6027ull, + 0xd5896d5c5c315cdaull, 0xe63c4fdada95da9eull, 0x50486018187818c0ull, 0x89cf05464643460aull, + 0x945913cdcddecd26ull, 0x136ee97d7d947dcfull, 0xc6e7842121a52115ull, 0x8737fab0b04ab0e9ull, + 0x82bdfc3f3fc33fe5ull, 0x5a416c1b1b771bd8ull, 0x11981e898997893cull, 0x38c7dbffff24ffabull, + 0x40ab8bebeb60eb0bull, 0x3fbb2a8484ae8454ull, 0x6b02b96969d0696full, 0x9ca6e83a3ad23acdull, + 0x69f44e9d9dd39d9cull, 0xc81f7bd7d7acd7f6ull, 0xd0036bd3d3b8d3d6ull, 0x3d4ddd7070ad70a7ull, + 0x4f28816767e6671full, 0x9ddd1d40405d403aull, 0x992ceeb5b55bb5c1ull, 0xfe205fdede81debeull, + 0xd38e695d5d345dd2ull, 0xa090c03030f0309dull, 0x41d07e9191ef91fcull, 0x8130feb1b14fb1e1ull, + 0x0d75fd78788578e7ull, 0x6677441111551188ull, 0x0607040101050108ull, 0x6481b3e5e556e57bull, + 0x0000000000000000ull, 0x6d05bd6868d56867ull, 0x77ef5a9898c298b4ull, 0xe747baa0a01aa069ull, + 0xa46133c5c5f6c566ull, 0x0c0e0802020a0210ull, 0xf355a2a6a604a659ull, 0x2551cd7474b97487ull, + 0xeec3b42d2d992d75ull, 0x3a312c0b0b270b58ull, 0xeb49b2a2a210a279ull, 0x295fc57676b37697ull, + 0x8d3ef6b3b345b3f1ull, 0xa31dc2bebe7cbe99ull, 0x9e501fceced1ce3eull, 0xa914cebdbd73bd81ull, + 0xc36d82aeae2cae19ull, 0x4ca583e9e96ae91bull, 0x1b91128a8a988a24ull, 0xa697c43131f53195ull, + 0x4854701c1c6c1ce0ull, 0x52be97ecec7bec33ull, 0x1cede3f1f112f1dbull, 0x71e85e9999c799bcull, + 0x5fcb6a9494fe94d4ull, 0xdb7192aaaa38aa39ull, 0x0ef8fff6f609f6e3ull, 0xd4f2982626be262dull, + 0xe2cdbc2f2f932f65ull, 0x58b79befef74ef2bull, 0x4aa287e8e86fe813ull, 0x0f830a8c8c868c14ull, + 0xbe8bd43535e135b5ull, 0x0a090c03030f0318ull, 0xc21677d4d4a3d4eeull, 0x1f60e17f7f9e7fdfull, + 0x20dbcbfbfb30fb8bull, 0x1e1b140505110528ull, 0xbc7d23c1c1e2c146ull, 0xd987655e5e3b5ecaull, + 0x47d77a9090ea90f4ull, 0xc0e0802020a0201dull, 0x8eb3f43d3dc93df5ull, 0x2ba9328282b08264ull, + 0x08fffbf7f70cf7ebull, 0x46ac8feaea65ea03ull, 0x3c36280a0a220a50ull, 0x2e23340d0d390d68ull, + 0x1967e57e7e9b7ed7ull, 0x2ad2c7f8f83ff893ull, 0xfdad5d50500d50baull, 0x5c46681a1a721ad0ull, + 0xa26637c4c4f3c46eull, 0x12151c07071b0738ull, 0xefb8415757165782ull, 0xb70fdab8b862b8a9ull, + 0x88b4f03c3ccc3cfdull, 0x5133956262f76237ull, 0x7093abe3e348e34bull, 0x8a4207c8c8cfc80eull, + 0xcf638aacac26ac09ull, 0xf1a35552520752aaull, 0x45218d6464e96407ull, 0x6070401010501080ull, + 0xda0a67d0d0b7d0ceull, 0xec3543d9d99ad986ull, 0x6a794c13135f1398ull, 0x2824300c0c3c0c60ull, + 0x6c7e4812125a1290ull, 0xf6dfa429298d2955ull, 0xfbaa5951510851b2ull, 0xb108deb9b967b9a1ull, + 0x98571bcfcfd4cf36ull, 0xce187fd6d6a9d6feull, 0x3744d17373a273bfull, 0x09840e8d8d838d1cull, + 0x21a03e8181bf817cull, 0xe5b14d545419549aull, 0xba7a27c0c0e7c04eull, 0x54b993eded7eed3bull, + 0xb9f7254e4e6b4e4aull, 0x85c10d444449441aull, 0xf552a6a7a701a751ull, 0xfcd6a82a2a822a4dull, + 0x39bc2e8585ab855cull, 0xdefb942525b12535ull, 0x6e88bfe6e659e663ull, 0x864c0fcacac5ca1eull, + 0x1569ed7c7c917cc7ull, 0x1d96168b8b9d8b2cull, 0xe9bf45565613568aull, 0x27a73a8080ba8074ull + }, + { + 0x501fceced1ce3e9eull, 0x06d6bbbb6dbbb1bdull, 0xab8bebeb60eb0b40ull, 0xd9729292e092e44bull, + 0xac8feaea65ea0346ull, 0x4b0bcbcbc0cb1680ull, 0x794c13135f13986aull, 0x7d23c1c1e2c146bcull, + 0xa583e9e96ae91b4cull, 0xa6e83a3ad23acd9cull, 0x187fd6d6a9d6feceull, 0x39f2b2b240b2f98bull, + 0x046fd2d2bdd2ded6ull, 0xd77a9090ea90f447ull, 0x655c17174b17b872ull, 0xd2c7f8f83ff8932aull, + 0xd315424257422a91ull, 0x6b5415154115a87eull, 0xbf45565613568ae9ull, 0x2beab4b45eb4c99full, + 0x26896565ec650f43ull, 0x54701c1c6c1ce048ull, 0x9f1a888892883417ull, 0xd411434352432297ull, + 0x6133c5c5f6c566a4ull, 0x896d5c5c315cdad5ull, 0x82d83636ee36adb4ull, 0x01d2baba68bab9bbull, + 0xf1f3f5f506f5fb04ull, 0xb8415757165782efull, 0x28816767e6671f4full, 0x840e8d8d838d1c09ull, + 0x97c43131f53195a6ull, 0xf8fff6f609f6e30eull, 0x218d6464e9640745ull, 0x957d58582558facdull, + 0xfd429e9edc9e8463ull, 0xf6f7f4f403f4f302ull, 0xee882222aa220dccull, 0x7192aaaa38aa39dbull, + 0x56c97575bc758f23ull, 0x2d3c0f0f330f7822ull, 0x0e0802020a02100cull, 0x30feb1b14fb1e181ull, + 0x275bdfdf84dfb6f8ull, 0x1ea96d6dc46d4f73ull, 0x44d17373a273bf37ull, 0xfe294d4d644d52b3ull, + 0x69ed7c7c917cc715ull, 0xf2982626be262dd4ull, 0xcab82e2e962e6de4ull, 0xfffbf7f70cf7eb08ull, + 0x3820080828084030ull, 0x8e695d5d345dd2d3ull, 0xc10d444449441a85ull, 0xbaf83e3ec63eed84ull, + 0xfa469f9fd99f8c65ull, 0x6c5014144414a078ull, 0x4207c8c8cfc80e8aull, 0x6d82aeae2cae19c3ull, + 0xb14d545419549ae5ull, 0x7040101050108060ull, 0x3247d8d89fd88eeaull, 0x13cabcbc76bc89afull, + 0x46681a1a721ad05cull, 0x0cb16b6bda6b7f67ull, 0x02b96969d0696f6bull, 0xe3ebf3f318f3cb10ull, + 0x14cebdbd73bd81a9ull, 0x99cc3333ff3385aaull, 0x7696abab3dab31ddull, 0xdccffafa35fa8326ull, + 0x0d63d1d1b2d1c6dcull, 0xe6569b9bcd9bac7dull, 0x05bd6868d568676dull, 0xf7254e4e6b4e4ab9ull, + 0x625816164e16b074ull, 0xcc6e9595fb95dc59ull, 0xd07e9191ef91fc41ull, 0xb09feeee71ee235eull, + 0xf92d4c4c614c5ab5ull, 0x34916363f2633f57ull, 0x8d028e8e8c8e0403ull, 0x9c715b5b2a5be2c7ull, + 0x5e17ccccdbcc2e92ull, 0xb4f03c3ccc3cfd88ull, 0x4f6419197d19c856ull, 0x40bea1a11fa161e1ull, + 0xa03e8181bf817c21ull, 0xe2394949704972abull, 0x7cf17b7b8a7bff07ull, 0x3543d9d99ad986ecull, + 0x10a16f6fce6f5f7full, 0x85dc3737eb37a5b2ull, 0x3d9d6060fd60275dull, 0x4c0fcacac5ca1e86ull, + 0x8fbbe7e75ce76b68ull, 0xd1ac2b2b872b45faull, 0xe53d484875487aadull, 0xc9d3fdfd2efdbb34ull, + 0xc5629696f496c453ull, 0xc60945454c451283ull, 0xced7fcfc2bfcb332ull, 0xda1941415841329bull, + 0x7e4812125a12906cull, 0x23340d0d390d682eull, 0x72f979798079ef0bull, 0x81b3e5e556e57b64ull, + 0x981e898997893c11ull, 0x830a8c8c868c140full, 0x93abe3e348e34b70ull, 0xe0802020a0201dc0ull, + 0x90c03030f0309da0ull, 0x2e57dcdc8bdcaef2ull, 0x22e6b7b751b7d195ull, 0x19ad6c6cc16c4775ull, + 0xeb354a4a7f4a6aa1ull, 0x2ceeb5b55bb5c199ull, 0xbdfc3f3fc33fe582ull, 0xc2669797f197cc55ull, + 0x1677d4d4a3d4eec2ull, 0x33956262f7623751ull, 0xc3b42d2d992d75eeull, 0x121806061e063014ull, + 0x5baaa4a40ea449ffull, 0x5caea5a50ba541f9ull, 0xae368383b5836c2dull, 0x80615f5f3e5fc2dfull, + 0xd6a82a2a822a4dfcull, 0x3c4fdada95da9ee6ull, 0x4503c9c9cac9068cull, 0x0000000000000000ull, + 0x67e57e7e9b7ed719ull, 0x49b2a2a210a279ebull, 0xb64955551c5592e3ull, 0x1ac6bfbf79bf91a5ull, + 0x7744111155118866ull, 0x1173d5d5a6d5e6c4ull, 0xf34a9c9cd69c946full, 0x571bcfcfd4cf3698ull, + 0x2a380e0e360e7024ull, 0x36280a0a220a503cull, 0xb3f43d3dc93df58eull, 0xaa5951510851b2fbull, + 0x6ee97d7d947dcf13ull, 0xde769393e593ec4dull, 0x416c1b1b771bd85aull, 0xc0dffefe21fea33eull, + 0x6637c4c4f3c46ea2ull, 0xc80147474647028full, 0x3f2409092d094836ull, 0xb5228686a4864433ull, + 0x312c0b0b270b583aull, 0x8a068f8f898f0c05ull, 0xf44e9d9dd39d9c69ull, 0x0bb56a6adf6a7761ull, + 0x151c07071b073812ull, 0x08deb9b967b9a1b1ull, 0x37fab0b04ab0e987ull, 0xef5a9898c298b477ull, + 0x486018187818c050ull, 0x9ec83232fa328dacull, 0x4ad97171a871af3bull, 0xec314b4b7a4b62a7ull, + 0xb79befef74ef2b58ull, 0xa1ec3b3bd73bc59aull, 0x4ddd7070ad70a73dull, 0x47baa0a01aa069e7ull, + 0x86b7e4e453e47362ull, 0xdd1d40405d403a9dull, 0xc7dbffff24ffab38ull, 0x732bc3c3e8c356b0ull, + 0x789ea9a937a921d1ull, 0x88bfe6e659e6636eull, 0x75fd78788578e70dull, 0xd5c3f9f93af99b2cull, + 0x96168b8b9d8b2c1dull, 0xcf05464643460a89ull, 0xa73a8080ba807427ull, 0x5a781e1e661ef044ull, + 0xa8e03838d838dd90ull, 0x9da3e1e142e15b7cull, 0x0fdab8b862b8a9b7ull, 0x7f9aa8a832a829d7ull, + 0x9aa7e0e047e0537aull, 0x24300c0c3c0c6028ull, 0xe98c2323af2305caull, 0x5fc57676b3769729ull, + 0x53741d1d691de84eull, 0xfb942525b12535deull, 0xfc902424b4243dd8ull, 0x1b1405051105281eull, + 0xede3f1f112f1db1cull, 0x17a56e6ecb6e5779ull, 0xcb6a9494fe94d45full, 0xd8a0282888285df0ull, + 0xe1529a9ac89aa47bull, 0xbb2a8484ae84543full, 0xa287e8e86fe8134aull, 0x4eb6a3a315a371edull, + 0xf0214f4f6e4f42bfull, 0x58c17777b6779f2full, 0x036bd3d3b8d3d6d0ull, 0xbc2e8585ab855c39ull, + 0x94afe2e24de24376ull, 0xa35552520752aaf1ull, 0xe4eff2f21df2c316ull, 0xa9328282b082642bull, + 0xad5d50500d50bafdull, 0x7bf57a7a8f7af701ull, 0xcdbc2f2f932f65e2ull, 0x51cd7474b9748725ull, + 0xa45153530253a2f7ull, 0x3ef6b3b345b3f18dull, 0x3a996161f8612f5bull, 0x6a86afaf29af11c5ull, + 0xafe43939dd39d596ull, 0x8bd43535e135b5beull, 0x205fdede81debefeull, 0x5913cdcddecd2694ull, + 0x5d7c1f1f631ff842ull, 0xe85e9999c799bc71ull, 0x638aacac26ac09cfull, 0x648eadad23ad01c9ull, + 0x43d57272a772b731ull, 0xc4b02c2c9c2c7de8ull, 0x2953dddd8edda6f4ull, 0x0a67d0d0b7d0cedaull, + 0xb2268787a1874c35ull, 0x1dc2bebe7cbe99a3ull, 0x87655e5e3b5ecad9ull, 0x55a2a6a604a659f3ull, + 0xbe97ecec7bec3352ull, 0x1c10040414042018ull, 0x683fc6c6f9c67eaeull, 0x090c03030f03180aull, + 0x8cd03434e434bdb8ull, 0xdbcbfbfb30fb8b20ull, 0x3b4bdbdb90db96e0ull, 0x927959592059f2cbull, + 0x25e2b6b654b6d993ull, 0x742fc2c2edc25eb6ull, 0x0704010105010806ull, 0xeae7f0f017f0d31aull, + 0x9b755a5a2f5aeac1ull, 0xb993eded7eed3b54ull, 0x52a6a7a701a751f5ull, 0x2f856666e3661749ull, + 0xe7842121a52115c6ull, 0x60e17f7f9e7fdf1full, 0x91128a8a988a241bull, 0xf59c2727bb2725d2ull, + 0x6f3bc7c7fcc776a8ull, 0x7a27c0c0e7c04ebaull, 0xdfa429298d2955f6ull, 0x1f7bd7d7acd7f6c8ull + }, + { + 0x769393e593ec4ddeull, 0x43d9d99ad986ec35ull, 0x529a9ac89aa47be1ull, 0xeeb5b55bb5c1992cull, + 0x5a9898c298b477efull, 0x882222aa220dcceeull, 0x0945454c451283c6ull, 0xd7fcfc2bfcb332ceull, + 0xd2baba68bab9bb01ull, 0xb56a6adf6a77610bull, 0x5bdfdf84dfb6f827ull, 0x0802020a02100c0eull, + 0x469f9fd99f8c65faull, 0x57dcdc8bdcaef22eull, 0x5951510851b2fbaaull, 0x7959592059f2cb92ull, + 0x354a4a7f4a6aa1ebull, 0x5c17174b17b87265ull, 0xac2b2b872b45fad1ull, 0x2fc2c2edc25eb674ull, + 0x6a9494fe94d45fcbull, 0xf7f4f403f4f302f6ull, 0xd6bbbb6dbbb1bd06ull, 0xb6a3a315a371ed4eull, + 0x956262f762375133ull, 0xb7e4e453e4736286ull, 0xd97171a871af3b4aull, 0x77d4d4a3d4eec216ull, + 0x13cdcddecd269459ull, 0xdd7070ad70a73d4dull, 0x5816164e16b07462ull, 0xa3e1e142e15b7c9dull, + 0x394949704972abe2ull, 0xf03c3ccc3cfd88b4ull, 0x27c0c0e7c04eba7aull, 0x47d8d89fd88eea32ull, + 0x6d5c5c315cdad589ull, 0x569b9bcd9bac7de6ull, 0x8eadad23ad01c964ull, 0x2e8585ab855c39bcull, + 0x5153530253a2f7a4ull, 0xbea1a11fa161e140ull, 0xf57a7a8f7af7017bull, 0x07c8c8cfc80e8a42ull, + 0xb42d2d992d75eec3ull, 0xa7e0e047e0537a9aull, 0x63d1d1b2d1c6dc0dull, 0xd57272a772b73143ull, + 0xa2a6a604a659f355ull, 0xb02c2c9c2c7de8c4ull, 0x37c4c4f3c46ea266ull, 0xabe3e348e34b7093ull, + 0xc57676b37697295full, 0xfd78788578e70d75ull, 0xe6b7b751b7d19522ull, 0xeab4b45eb4c99f2bull, + 0x2409092d0948363full, 0xec3b3bd73bc59aa1ull, 0x380e0e360e70242aull, 0x1941415841329bdaull, + 0x2d4c4c614c5ab5f9ull, 0x5fdede81debefe20ull, 0xf2b2b240b2f98b39ull, 0x7a9090ea90f447d7ull, + 0x942525b12535defbull, 0xaea5a50ba541f95cull, 0x7bd7d7acd7f6c81full, 0x0c03030f03180a09ull, + 0x4411115511886677ull, 0x0000000000000000ull, 0x2bc3c3e8c356b073ull, 0xb82e2e962e6de4caull, + 0x729292e092e44bd9ull, 0x9befef74ef2b58b7ull, 0x254e4e6b4e4ab9f7ull, 0x4812125a12906c7eull, + 0x4e9d9dd39d9c69f4ull, 0xe97d7d947dcf136eull, 0x0bcbcbc0cb16804bull, 0xd43535e135b5be8bull, + 0x4010105010806070ull, 0x73d5d5a6d5e6c411ull, 0x214f4f6e4f42bff0ull, 0x429e9edc9e8463fdull, + 0x294d4d644d52b3feull, 0x9ea9a937a921d178ull, 0x4955551c5592e3b6ull, 0x3fc6c6f9c67eae68ull, + 0x67d0d0b7d0ceda0aull, 0xf17b7b8a7bff077cull, 0x6018187818c05048ull, 0x669797f197cc55c2ull, + 0x6bd3d3b8d3d6d003ull, 0xd83636ee36adb482ull, 0xbfe6e659e6636e88ull, 0x3d484875487aade5ull, + 0x45565613568ae9bfull, 0x3e8181bf817c21a0ull, 0x068f8f898f0c058aull, 0xc17777b6779f2f58ull, + 0x17ccccdbcc2e925eull, 0x4a9c9cd69c946ff3ull, 0xdeb9b967b9a1b108ull, 0xafe2e24de2437694ull, + 0x8aacac26ac09cf63ull, 0xdab8b862b8a9b70full, 0xbc2f2f932f65e2cdull, 0x5415154115a87e6bull, + 0xaaa4a40ea449ff5bull, 0xed7c7c917cc71569ull, 0x4fdada95da9ee63cull, 0xe03838d838dd90a8ull, + 0x781e1e661ef0445aull, 0x2c0b0b270b583a31ull, 0x1405051105281e1bull, 0x7fd6d6a9d6fece18ull, + 0x5014144414a0786cull, 0xa56e6ecb6e577917ull, 0xad6c6cc16c477519ull, 0xe57e7e9b7ed71967ull, + 0x856666e36617492full, 0xd3fdfd2efdbb34c9ull, 0xfeb1b14fb1e18130ull, 0xb3e5e556e57b6481ull, + 0x9d6060fd60275d3dull, 0x86afaf29af11c56aull, 0x655e5e3b5ecad987ull, 0xcc3333ff3385aa99ull, + 0x268787a1874c35b2ull, 0x03c9c9cac9068c45ull, 0xe7f0f017f0d31aeaull, 0x695d5d345dd2d38eull, + 0xa96d6dc46d4f731eull, 0xfc3f3fc33fe582bdull, 0x1a8888928834179full, 0x0e8d8d838d1c0984ull, + 0x3bc7c7fcc776a86full, 0xfbf7f70cf7eb08ffull, 0x741d1d691de84e53ull, 0x83e9e96ae91b4ca5ull, + 0x97ecec7bec3352beull, 0x93eded7eed3b54b9ull, 0x3a8080ba807427a7ull, 0xa429298d2955f6dfull, + 0x9c2727bb2725d2f5ull, 0x1bcfcfd4cf369857ull, 0x5e9999c799bc71e8ull, 0x9aa8a832a829d77full, + 0x5d50500d50bafdadull, 0x3c0f0f330f78222dull, 0xdc3737eb37a5b285ull, 0x902424b4243dd8fcull, + 0xa0282888285df0d8ull, 0xc03030f0309da090ull, 0x6e9595fb95dc59ccull, 0x6fd2d2bdd2ded604ull, + 0xf83e3ec63eed84baull, 0x715b5b2a5be2c79cull, 0x1d40405d403a9dddull, 0x368383b5836c2daeull, + 0xf6b3b345b3f18d3eull, 0xb96969d0696f6b02ull, 0x415757165782efb8ull, 0x7c1f1f631ff8425dull, + 0x1c07071b07381215ull, 0x701c1c6c1ce04854ull, 0x128a8a988a241b91ull, 0xcabcbc76bc89af13ull, + 0x802020a0201dc0e0ull, 0x8bebeb60eb0b40abull, 0x1fceced1ce3e9e50ull, 0x028e8e8c8e04038dull, + 0x96abab3dab31dd76ull, 0x9feeee71ee235eb0ull, 0xc43131f53195a697ull, 0xb2a2a210a279eb49ull, + 0xd17373a273bf3744ull, 0xc3f9f93af99b2cd5ull, 0x0fcacac5ca1e864cull, 0xe83a3ad23acd9ca6ull, + 0x681a1a721ad05c46ull, 0xcbfbfb30fb8b20dbull, 0x340d0d390d682e23ull, 0x23c1c1e2c146bc7dull, + 0xdffefe21fea33ec0ull, 0xcffafa35fa8326dcull, 0xeff2f21df2c316e4ull, 0xa16f6fce6f5f7f10ull, + 0xcebdbd73bd81a914ull, 0x629696f496c453c5ull, 0x53dddd8edda6f429ull, 0x11434352432297d4ull, + 0x5552520752aaf1a3ull, 0xe2b6b654b6d99325ull, 0x2008082808403038ull, 0xebf3f318f3cb10e3ull, + 0x82aeae2cae19c36dull, 0xc2bebe7cbe99a31dull, 0x6419197d19c8564full, 0x1e898997893c1198ull, + 0xc83232fa328dac9eull, 0x982626be262dd4f2ull, 0xfab0b04ab0e98737ull, 0x8feaea65ea0346acull, + 0x314b4b7a4b62a7ecull, 0x8d6464e964074521ull, 0x2a8484ae84543fbbull, 0x328282b082642ba9ull, + 0xb16b6bda6b7f670cull, 0xf3f5f506f5fb04f1ull, 0xf979798079ef0b72ull, 0xc6bfbf79bf91a51aull, + 0x0401010501080607ull, 0x615f5f3e5fc2df80ull, 0xc97575bc758f2356ull, 0x916363f2633f5734ull, + 0x6c1b1b771bd85a41ull, 0x8c2323af2305cae9ull, 0xf43d3dc93df58eb3ull, 0xbd6868d568676d05ull, + 0xa82a2a822a4dfcd6ull, 0x896565ec650f4326ull, 0x87e8e86fe8134aa2ull, 0x7e9191ef91fc41d0ull, + 0xfff6f609f6e30ef8ull, 0xdbffff24ffab38c7ull, 0x4c13135f13986a79ull, 0x7d58582558facd95ull, + 0xe3f1f112f1db1cedull, 0x0147474647028fc8ull, 0x280a0a220a503c36ull, 0xe17f7f9e7fdf1f60ull, + 0x33c5c5f6c566a461ull, 0xa6a7a701a751f552ull, 0xbbe7e75ce76b688full, 0x996161f8612f5b3aull, + 0x755a5a2f5aeac19bull, 0x1806061e06301412ull, 0x05464643460a89cfull, 0x0d444449441a85c1ull, + 0x15424257422a91d3ull, 0x100404140420181cull, 0xbaa0a01aa069e747ull, 0x4bdbdb90db96e03bull, + 0xe43939dd39d596afull, 0x228686a4864433b5ull, 0x4d545419549ae5b1ull, 0x92aaaa38aa39db71ull, + 0x0a8c8c868c140f83ull, 0xd03434e434bdb88cull, 0x842121a52115c6e7ull, 0x168b8b9d8b2c1d96ull, + 0xc7f8f83ff8932ad2ull, 0x300c0c3c0c602824ull, 0xcd7474b974872551ull, 0x816767e6671f4f28ull + }, + { + 0x6868d568676d05bdull, 0x8d8d838d1c09840eull, 0xcacac5ca1e864c0full, 0x4d4d644d52b3fe29ull, + 0x7373a273bf3744d1ull, 0x4b4b7a4b62a7ec31ull, 0x4e4e6b4e4ab9f725ull, 0x2a2a822a4dfcd6a8ull, + 0xd4d4a3d4eec21677ull, 0x52520752aaf1a355ull, 0x2626be262dd4f298ull, 0xb3b345b3f18d3ef6ull, + 0x545419549ae5b14dull, 0x1e1e661ef0445a78ull, 0x19197d19c8564f64ull, 0x1f1f631ff8425d7cull, + 0x2222aa220dccee88ull, 0x03030f03180a090cull, 0x464643460a89cf05ull, 0x3d3dc93df58eb3f4ull, + 0x2d2d992d75eec3b4ull, 0x4a4a7f4a6aa1eb35ull, 0x53530253a2f7a451ull, 0x8383b5836c2dae36ull, + 0x13135f13986a794cull, 0x8a8a988a241b9112ull, 0xb7b751b7d19522e6ull, 0xd5d5a6d5e6c41173ull, + 0x2525b12535defb94ull, 0x79798079ef0b72f9ull, 0xf5f506f5fb04f1f3ull, 0xbdbd73bd81a914ceull, + 0x58582558facd957dull, 0x2f2f932f65e2cdbcull, 0x0d0d390d682e2334ull, 0x02020a02100c0e08ull, + 0xeded7eed3b54b993ull, 0x51510851b2fbaa59ull, 0x9e9edc9e8463fd42ull, 0x1111551188667744ull, + 0xf2f21df2c316e4efull, 0x3e3ec63eed84baf8ull, 0x55551c5592e3b649ull, 0x5e5e3b5ecad98765ull, + 0xd1d1b2d1c6dc0d63ull, 0x16164e16b0746258ull, 0x3c3ccc3cfd88b4f0ull, 0x6666e36617492f85ull, + 0x7070ad70a73d4dddull, 0x5d5d345dd2d38e69ull, 0xf3f318f3cb10e3ebull, 0x45454c451283c609ull, + 0x40405d403a9ddd1dull, 0xccccdbcc2e925e17ull, 0xe8e86fe8134aa287ull, 0x9494fe94d45fcb6aull, + 0x565613568ae9bf45ull, 0x0808280840303820ull, 0xceced1ce3e9e501full, 0x1a1a721ad05c4668ull, + 0x3a3ad23acd9ca6e8ull, 0xd2d2bdd2ded6046full, 0xe1e142e15b7c9da3ull, 0xdfdf84dfb6f8275bull, + 0xb5b55bb5c1992ceeull, 0x3838d838dd90a8e0ull, 0x6e6ecb6e577917a5ull, 0x0e0e360e70242a38ull, + 0xe5e556e57b6481b3ull, 0xf4f403f4f302f6f7ull, 0xf9f93af99b2cd5c3ull, 0x8686a4864433b522ull, + 0xe9e96ae91b4ca583ull, 0x4f4f6e4f42bff021ull, 0xd6d6a9d6fece187full, 0x8585ab855c39bc2eull, + 0x2323af2305cae98cull, 0xcfcfd4cf3698571bull, 0x3232fa328dac9ec8ull, 0x9999c799bc71e85eull, + 0x3131f53195a697c4ull, 0x14144414a0786c50ull, 0xaeae2cae19c36d82ull, 0xeeee71ee235eb09full, + 0xc8c8cfc80e8a4207ull, 0x484875487aade53dull, 0xd3d3b8d3d6d0036bull, 0x3030f0309da090c0ull, + 0xa1a11fa161e140beull, 0x9292e092e44bd972ull, 0x41415841329bda19ull, 0xb1b14fb1e18130feull, + 0x18187818c0504860ull, 0xc4c4f3c46ea26637ull, 0x2c2c9c2c7de8c4b0ull, 0x7171a871af3b4ad9ull, + 0x7272a772b73143d5ull, 0x444449441a85c10dull, 0x15154115a87e6b54ull, 0xfdfd2efdbb34c9d3ull, + 0x3737eb37a5b285dcull, 0xbebe7cbe99a31dc2ull, 0x5f5f3e5fc2df8061ull, 0xaaaa38aa39db7192ull, + 0x9b9bcd9bac7de656ull, 0x8888928834179f1aull, 0xd8d89fd88eea3247ull, 0xabab3dab31dd7696ull, + 0x898997893c11981eull, 0x9c9cd69c946ff34aull, 0xfafa35fa8326dccfull, 0x6060fd60275d3d9dull, + 0xeaea65ea0346ac8full, 0xbcbc76bc89af13caull, 0x6262f76237513395ull, 0x0c0c3c0c60282430ull, + 0x2424b4243dd8fc90ull, 0xa6a604a659f355a2ull, 0xa8a832a829d77f9aull, 0xecec7bec3352be97ull, + 0x6767e6671f4f2881ull, 0x2020a0201dc0e080ull, 0xdbdb90db96e03b4bull, 0x7c7c917cc71569edull, + 0x282888285df0d8a0ull, 0xdddd8edda6f42953ull, 0xacac26ac09cf638aull, 0x5b5b2a5be2c79c71ull, + 0x3434e434bdb88cd0ull, 0x7e7e9b7ed71967e5ull, 0x1010501080607040ull, 0xf1f112f1db1cede3ull, + 0x7b7b8a7bff077cf1ull, 0x8f8f898f0c058a06ull, 0x6363f2633f573491ull, 0xa0a01aa069e747baull, + 0x05051105281e1b14ull, 0x9a9ac89aa47be152ull, 0x434352432297d411ull, 0x7777b6779f2f58c1ull, + 0x2121a52115c6e784ull, 0xbfbf79bf91a51ac6ull, 0x2727bb2725d2f59cull, 0x09092d0948363f24ull, + 0xc3c3e8c356b0732bull, 0x9f9fd99f8c65fa46ull, 0xb6b654b6d99325e2ull, 0xd7d7acd7f6c81f7bull, + 0x29298d2955f6dfa4ull, 0xc2c2edc25eb6742full, 0xebeb60eb0b40ab8bull, 0xc0c0e7c04eba7a27ull, + 0xa4a40ea449ff5baaull, 0x8b8b9d8b2c1d9616ull, 0x8c8c868c140f830aull, 0x1d1d691de84e5374ull, + 0xfbfb30fb8b20dbcbull, 0xffff24ffab38c7dbull, 0xc1c1e2c146bc7d23ull, 0xb2b240b2f98b39f2ull, + 0x9797f197cc55c266ull, 0x2e2e962e6de4cab8ull, 0xf8f83ff8932ad2c7ull, 0x6565ec650f432689ull, + 0xf6f609f6e30ef8ffull, 0x7575bc758f2356c9ull, 0x07071b073812151cull, 0x0404140420181c10ull, + 0x4949704972abe239ull, 0x3333ff3385aa99ccull, 0xe4e453e4736286b7ull, 0xd9d99ad986ec3543ull, + 0xb9b967b9a1b108deull, 0xd0d0b7d0ceda0a67ull, 0x424257422a91d315ull, 0xc7c7fcc776a86f3bull, + 0x6c6cc16c477519adull, 0x9090ea90f447d77aull, 0x0000000000000000ull, 0x8e8e8c8e04038d02ull, + 0x6f6fce6f5f7f10a1ull, 0x50500d50bafdad5dull, 0x0101050108060704ull, 0xc5c5f6c566a46133ull, + 0xdada95da9ee63c4full, 0x47474647028fc801ull, 0x3f3fc33fe582bdfcull, 0xcdcddecd26945913ull, + 0x6969d0696f6b02b9ull, 0xa2a210a279eb49b2ull, 0xe2e24de2437694afull, 0x7a7a8f7af7017bf5ull, + 0xa7a701a751f552a6ull, 0xc6c6f9c67eae683full, 0x9393e593ec4dde76ull, 0x0f0f330f78222d3cull, + 0x0a0a220a503c3628ull, 0x06061e0630141218ull, 0xe6e659e6636e88bfull, 0x2b2b872b45fad1acull, + 0x9696f496c453c562ull, 0xa3a315a371ed4eb6ull, 0x1c1c6c1ce0485470ull, 0xafaf29af11c56a86ull, + 0x6a6adf6a77610bb5ull, 0x12125a12906c7e48ull, 0x8484ae84543fbb2aull, 0x3939dd39d596afe4ull, + 0xe7e75ce76b688fbbull, 0xb0b04ab0e98737faull, 0x8282b082642ba932ull, 0xf7f70cf7eb08fffbull, + 0xfefe21fea33ec0dfull, 0x9d9dd39d9c69f44eull, 0x8787a1874c35b226ull, 0x5c5c315cdad5896dull, + 0x8181bf817c21a03eull, 0x3535e135b5be8bd4ull, 0xdede81debefe205full, 0xb4b45eb4c99f2beaull, + 0xa5a50ba541f95caeull, 0xfcfc2bfcb332ced7ull, 0x8080ba807427a73aull, 0xefef74ef2b58b79bull, + 0xcbcbc0cb16804b0bull, 0xbbbb6dbbb1bd06d6ull, 0x6b6bda6b7f670cb1ull, 0x7676b37697295fc5ull, + 0xbaba68bab9bb01d2ull, 0x5a5a2f5aeac19b75ull, 0x7d7d947dcf136ee9ull, 0x78788578e70d75fdull, + 0x0b0b270b583a312cull, 0x9595fb95dc59cc6eull, 0xe3e348e34b7093abull, 0xadad23ad01c9648eull, + 0x7474b974872551cdull, 0x9898c298b477ef5aull, 0x3b3bd73bc59aa1ecull, 0x3636ee36adb482d8ull, + 0x6464e9640745218dull, 0x6d6dc46d4f731ea9ull, 0xdcdc8bdcaef22e57ull, 0xf0f017f0d31aeae7ull, + 0x59592059f2cb9279ull, 0xa9a937a921d1789eull, 0x4c4c614c5ab5f92dull, 0x17174b17b872655cull, + 0x7f7f9e7fdf1f60e1ull, 0x9191ef91fc41d07eull, 0xb8b862b8a9b70fdaull, 0xc9c9cac9068c4503ull, + 0x5757165782efb841ull, 0x1b1b771bd85a416cull, 0xe0e047e0537a9aa7ull, 0x6161f8612f5b3a99ull + } +}; + +} // namespace detail + +} // namespace digestpp + +#endif \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/detail/constants/md5_constants.hpp b/ext/include/digestpp/algorithm/detail/constants/md5_constants.hpp new file mode 100644 index 0000000..0a9d3d1 --- /dev/null +++ b/ext/include/digestpp/algorithm/detail/constants/md5_constants.hpp @@ -0,0 +1,43 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_PROVIDERS_MD5_CONSTANTS_HPP +#define DIGESTPP_PROVIDERS_MD5_CONSTANTS_HPP + +namespace digestpp +{ + +namespace detail +{ + +template +struct md5_constants +{ + const static uint32_t K[64]; + const static unsigned char S[64]; +}; + +template +const uint32_t md5_constants::K[64] = { + 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, + 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, + 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, + 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, + 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, + 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, + 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, + 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 +}; + +template +const unsigned char md5_constants::S[64] = { + 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 4, + 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21 +}; + +} // namespace detail + +} // namespace digestpp + +#endif \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/detail/constants/sha1_constants.hpp b/ext/include/digestpp/algorithm/detail/constants/sha1_constants.hpp new file mode 100644 index 0000000..3a273a1 --- /dev/null +++ b/ext/include/digestpp/algorithm/detail/constants/sha1_constants.hpp @@ -0,0 +1,29 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_PROVIDERS_SHA1_CONSTANTS_HPP +#define DIGESTPP_PROVIDERS_SHA1_CONSTANTS_HPP + +namespace digestpp +{ + +namespace detail +{ + +template +struct sha1_constants +{ + const static uint32_t K[4]; +}; + +template +const uint32_t sha1_constants::K[4] = { + 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6 +}; + +} // namespace detail + +} // namespace digestpp + +#endif \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/detail/constants/sha2_constants.hpp b/ext/include/digestpp/algorithm/detail/constants/sha2_constants.hpp new file mode 100644 index 0000000..8d826cb --- /dev/null +++ b/ext/include/digestpp/algorithm/detail/constants/sha2_constants.hpp @@ -0,0 +1,66 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_PROVIDERS_SHA2_CONSTANTS_HPP +#define DIGESTPP_PROVIDERS_SHA2_CONSTANTS_HPP + +namespace digestpp +{ + +namespace detail +{ + +template +struct sha512_constants +{ + const static uint64_t K[80]; +}; + +template +const uint64_t sha512_constants::K[80] = { + 0x428a2f98d728ae22ull, 0x7137449123ef65cdull, 0xb5c0fbcfec4d3b2full, 0xe9b5dba58189dbbcull, + 0x3956c25bf348b538ull, 0x59f111f1b605d019ull, 0x923f82a4af194f9bull, 0xab1c5ed5da6d8118ull, + 0xd807aa98a3030242ull, 0x12835b0145706fbeull, 0x243185be4ee4b28cull, 0x550c7dc3d5ffb4e2ull, + 0x72be5d74f27b896full, 0x80deb1fe3b1696b1ull, 0x9bdc06a725c71235ull, 0xc19bf174cf692694ull, + 0xe49b69c19ef14ad2ull, 0xefbe4786384f25e3ull, 0x0fc19dc68b8cd5b5ull, 0x240ca1cc77ac9c65ull, + 0x2de92c6f592b0275ull, 0x4a7484aa6ea6e483ull, 0x5cb0a9dcbd41fbd4ull, 0x76f988da831153b5ull, + 0x983e5152ee66dfabull, 0xa831c66d2db43210ull, 0xb00327c898fb213full, 0xbf597fc7beef0ee4ull, + 0xc6e00bf33da88fc2ull, 0xd5a79147930aa725ull, 0x06ca6351e003826full, 0x142929670a0e6e70ull, + 0x27b70a8546d22ffcull, 0x2e1b21385c26c926ull, 0x4d2c6dfc5ac42aedull, 0x53380d139d95b3dfull, + 0x650a73548baf63deull, 0x766a0abb3c77b2a8ull, 0x81c2c92e47edaee6ull, 0x92722c851482353bull, + 0xa2bfe8a14cf10364ull, 0xa81a664bbc423001ull, 0xc24b8b70d0f89791ull, 0xc76c51a30654be30ull, + 0xd192e819d6ef5218ull, 0xd69906245565a910ull, 0xf40e35855771202aull, 0x106aa07032bbd1b8ull, + 0x19a4c116b8d2d0c8ull, 0x1e376c085141ab53ull, 0x2748774cdf8eeb99ull, 0x34b0bcb5e19b48a8ull, + 0x391c0cb3c5c95a63ull, 0x4ed8aa4ae3418acbull, 0x5b9cca4f7763e373ull, 0x682e6ff3d6b2b8a3ull, + 0x748f82ee5defb2fcull, 0x78a5636f43172f60ull, 0x84c87814a1f0ab72ull, 0x8cc702081a6439ecull, + 0x90befffa23631e28ull, 0xa4506cebde82bde9ull, 0xbef9a3f7b2c67915ull, 0xc67178f2e372532bull, + 0xca273eceea26619cull, 0xd186b8c721c0c207ull, 0xeada7dd6cde0eb1eull, 0xf57d4f7fee6ed178ull, + 0x06f067aa72176fbaull, 0x0a637dc5a2c898a6ull, 0x113f9804bef90daeull, 0x1b710b35131c471bull, + 0x28db77f523047d84ull, 0x32caab7b40c72493ull, 0x3c9ebe0a15c9bebcull, 0x431d67c49c100d4cull, + 0x4cc5d4becb3e42b6ull, 0x597f299cfc657e2aull, 0x5fcb6fab3ad6faecull, 0x6c44198c4a475817ull +}; + +template +struct sha256_constants +{ + const static uint32_t K[64]; +}; + +template +const uint32_t sha256_constants::K[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +} // namespace detail + +} // namespace digestpp + +#endif \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/detail/constants/sha3_constants.hpp b/ext/include/digestpp/algorithm/detail/constants/sha3_constants.hpp new file mode 100644 index 0000000..ff4c838 --- /dev/null +++ b/ext/include/digestpp/algorithm/detail/constants/sha3_constants.hpp @@ -0,0 +1,35 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_PROVIDERS_SHA3_CONSTANTS_HPP +#define DIGESTPP_PROVIDERS_SHA3_CONSTANTS_HPP + +namespace digestpp +{ + +namespace detail +{ + +template +struct sha3_constants +{ + const static uint64_t RC[24]; +}; + +template +const uint64_t sha3_constants::RC[24] = { + 0x0000000000000001ull, 0x0000000000008082ull, 0x800000000000808Aull, 0x8000000080008000ull, + 0x000000000000808Bull, 0x0000000080000001ull, 0x8000000080008081ull, 0x8000000000008009ull, + 0x000000000000008Aull, 0x0000000000000088ull, 0x0000000080008009ull, 0x000000008000000Aull, + 0x000000008000808Bull, 0x800000000000008Bull, 0x8000000000008089ull, 0x8000000000008003ull, + 0x8000000000008002ull, 0x8000000000000080ull, 0x000000000000800Aull, 0x800000008000000Aull, + 0x8000000080008081ull, 0x8000000000008080ull, 0x0000000080000001ull, 0x8000000080008008ull +}; + + +} // namespace detail + +} // namespace digestpp + +#endif // DIGESTPP_PROVIDERS_SHA3_CONSTANTS_HPP \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/detail/constants/skein_constants.hpp b/ext/include/digestpp/algorithm/detail/constants/skein_constants.hpp new file mode 100644 index 0000000..223ccf1 --- /dev/null +++ b/ext/include/digestpp/algorithm/detail/constants/skein_constants.hpp @@ -0,0 +1,75 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_PROVIDERS_SKEIN_CONSTANTS_HPP +#define DIGESTPP_PROVIDERS_SKEIN_CONSTANTS_HPP + +namespace digestpp +{ + +namespace detail +{ + +template +struct skein_constants +{ + const static unsigned C4[8][2]; + const static unsigned C8[8][4]; + const static unsigned C16[8][8]; + const static unsigned I4[8][4]; + const static unsigned I8[8][8]; + const static unsigned I16[8][16]; +}; + +template +const unsigned skein_constants::C4[8][2] = { + { 14, 16 }, { 52, 57 }, { 23, 40 }, { 5, 37 }, { 25, 33 }, { 46, 12 }, { 58, 22 }, { 32, 32 } +}; + +template +const unsigned skein_constants::C8[8][4] = { + { 46, 36, 19, 37 }, { 33, 27, 14, 42 }, { 17, 49, 36, 39 }, { 44, 9, 54, 56 }, + { 39, 30, 34, 24 }, { 13, 50, 10, 17 }, { 25, 29, 39, 43 }, { 8, 35, 56, 22 } +}; + +template +const unsigned skein_constants::C16[8][8]= { + { 24, 13, 8, 47, 8, 17, 22, 37 }, { 38, 19, 10, 55, 49, 18, 23, 52 }, + { 33, 4, 51, 13, 34, 41, 59, 17 }, { 5, 20, 48, 41, 47, 28, 16, 25 }, + { 41, 9, 37, 31, 12, 47, 44, 30 }, { 16, 34, 56, 51, 4, 53, 42, 41 }, + { 31, 44, 47, 46, 19, 42, 44, 25 }, { 9, 48, 35, 52, 23, 31, 37, 20 } + +}; + +template +const unsigned skein_constants::I4[8][4]= { + { 0, 1, 2, 3 }, { 0, 3, 2, 1 }, { 0, 1, 2, 3 }, { 0, 3, 2, 1 }, + { 0, 1, 2, 3 }, { 0, 3, 2, 1 }, { 0, 1, 2, 3 }, { 0, 3, 2, 1 } +}; + +template +const unsigned skein_constants::I8[8][8]= { + { 0, 1, 2, 3, 4, 5, 6, 7 }, { 2, 1, 4, 7, 6, 5, 0, 3 }, + { 4, 1, 6, 3, 0, 5, 2, 7 }, { 6, 1, 0, 7, 2, 5, 4, 3 }, + { 0, 1, 2, 3, 4, 5, 6, 7 }, { 2, 1, 4, 7, 6, 5, 0, 3 }, + { 4, 1, 6, 3, 0, 5, 2, 7 }, { 6, 1, 0, 7, 2, 5, 4, 3 } +}; + +template +const unsigned skein_constants::I16[8][16] = { + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, + { 0, 9, 2, 13, 6, 11, 4, 15, 10, 7, 12, 3, 14, 5, 8, 1 }, + { 0, 7, 2, 5, 4, 3, 6, 1, 12, 15, 14, 13, 8, 11, 10, 9 }, + { 0, 15, 2, 11, 6, 13, 4, 9, 14, 1, 8, 5, 10, 3, 12, 7 }, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, + { 0, 9, 2, 13, 6, 11, 4, 15, 10, 7, 12, 3, 14, 5, 8, 1 }, + { 0, 7, 2, 5, 4, 3, 6, 1, 12, 15, 14, 13, 8, 11, 10, 9 }, + { 0, 15, 2, 11, 6, 13, 4, 9, 14, 1, 8, 5, 10, 3, 12, 7 } +}; + +} // namespace detail + +} // namespace digestpp + +#endif \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/detail/constants/streebog_constants.hpp b/ext/include/digestpp/algorithm/detail/constants/streebog_constants.hpp new file mode 100644 index 0000000..09eddee --- /dev/null +++ b/ext/include/digestpp/algorithm/detail/constants/streebog_constants.hpp @@ -0,0 +1,586 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_PROVIDERS_STREEBOG_CONSTANTS_HPP +#define DIGESTPP_PROVIDERS_STREEBOG_CONSTANTS_HPP + +namespace digestpp +{ + +namespace detail +{ + +template +struct streebog_constants +{ + static const uint64_t T[8][256]; + static const uint64_t RC[12][8]; +}; + +template +const uint64_t streebog_constants::T[8][256] = { + { + 0xd01f715b5c7ef8e6ull, 0x16fa240980778325ull, 0xa8a42e857ee049c8ull, 0x6ac1068fa186465bull, + 0x6e417bd7a2e9320bull, 0x665c8167a437daabull, 0x7666681aa89617f6ull, 0x4b959163700bdcf5ull, + 0xf14be6b78df36248ull, 0xc585bd689a625cffull, 0x9557d7fca67d82cbull, 0x89f0b969af6dd366ull, + 0xb0833d48749f6c35ull, 0xa1998c23b1ecbc7cull, 0x8d70c431ac02a736ull, 0xd6dfbc2fd0a8b69eull, + 0x37aeb3e551fa198bull, 0x0b7d128a40b5cf9cull, 0x5a8f2008b5780cbcull, 0xedec882284e333e5ull, + 0xd25fc177d3c7c2ceull, 0x5e0f5d50b61778ecull, 0x1d873683c0c24cb9ull, 0xad040bcbb45d208cull, + 0x2f89a0285b853c76ull, 0x5732fff6791b8d58ull, 0x3e9311439ef6ec3full, 0xc9183a809fd3c00full, + 0x83adf3f5260a01eeull, 0xa6791941f4e8ef10ull, 0x103ae97d0ca1cd5dull, 0x2ce948121dee1b4aull, + 0x39738421dbf2bf53ull, 0x093da2a6cf0cf5b4ull, 0xcd9847d89cbcb45full, 0xf9561c078b2d8ae8ull, + 0x9c6a755a6971777full, 0xbc1ebaa0712ef0c5ull, 0x72e61542abf963a6ull, 0x78bb5fde229eb12eull, + 0x14ba94250fceb90dull, 0x844d6697630e5282ull, 0x98ea08026a1e032full, 0xf06bbea144217f5cull, + 0xdb6263d11ccb377aull, 0x641c314b2b8ee083ull, 0x320e96ab9b4770cfull, 0x1ee7deb986a96b85ull, + 0xe96cf57a878c47b5ull, 0xfdd6615f8842feb8ull, 0xc83862965601dd1bull, 0x2ea9f83e92572162ull, + 0xf876441142ff97fcull, 0xeb2c455608357d9dull, 0x5612a7e0b0c9904cull, 0x6c01cbfb2d500823ull, + 0x4548a6a7fa037a2dull, 0xabc4c6bf388b6ef4ull, 0xbade77d4fdf8bebdull, 0x799b07c8eb4cac3aull, + 0x0c9d87e805b19cf0ull, 0xcb588aac106afa27ull, 0xea0c1d40c1e76089ull, 0x2869354a1e816f1aull, + 0xff96d17307fbc490ull, 0x9f0a9d602f1a5043ull, 0x96373fc6e016a5f7ull, 0x5292dab8b3a6e41cull, + 0x9b8ae0382c752413ull, 0x4f15ec3b7364a8a5ull, 0x3fb349555724f12bull, 0xc7c50d4415db66d7ull, + 0x92b7429ee379d1a7ull, 0xd37f99611a15dfdaull, 0x231427c05e34a086ull, 0xa439a96d7b51d538ull, + 0xb403401077f01865ull, 0xdda2aea5901d7902ull, 0x0a5d4a9c8967d288ull, 0xc265280adf660f93ull, + 0x8bb0094520d4e94eull, 0x2a29856691385532ull, 0x42a833c5bf072941ull, 0x73c64d54622b7eb2ull, + 0x07e095624504536cull, 0x8a905153e906f45aull, 0x6f6123c16b3b2f1full, 0xc6e55552dc097bc3ull, + 0x4468feb133d16739ull, 0xe211e7f0c7398829ull, 0xa2f96419f7879b40ull, 0x19074bdbc3ad38e9ull, + 0xf4ebc3f9474e0b0cull, 0x43886bd376d53455ull, 0xd8028beb5aa01046ull, 0x51f23282f5cdc320ull, + 0xe7b1c2be0d84e16dull, 0x081dfab006dee8a0ull, 0x3b33340d544b857bull, 0x7f5bcabc679ae242ull, + 0x0edd37c48a08a6d8ull, 0x81ed43d9a9b33bc6ull, 0xb1a3655ebd4d7121ull, 0x69a1eeb5e7ed6167ull, + 0xf6ab73d5c8f73124ull, 0x1a67a3e185c61fd5ull, 0x2dc91004d43c065eull, 0x0240b02c8fb93a28ull, + 0x90f7f2b26cc0eb8full, 0x3cd3a16f114fd617ull, 0xaae49ea9f15973e0ull, 0x06c0cd748cd64e78ull, + 0xda423bc7d5192a6eull, 0xc345701c16b41287ull, 0x6d2193ede4821537ull, 0xfcf639494190e3acull, + 0x7c3b228621f1c57eull, 0xfb16ac2b0494b0c0ull, 0xbf7e529a3745d7f9ull, 0x6881b6a32e3f7c73ull, + 0xca78d2bad9b8e733ull, 0xbbfe2fc2342aa3a9ull, 0x0dbddffecc6381e4ull, 0x70a6a56e2440598eull, + 0xe4d12a844befc651ull, 0x8c509c2765d0ba22ull, 0xee8c6018c28814d9ull, 0x17da7c1f49a59e31ull, + 0x609c4c1328e194d3ull, 0xb3e3d57232f44b09ull, 0x91d7aaa4a512f69bull, 0x0ffd6fd243dabbccull, + 0x50d26a943c1fde34ull, 0x6be15e9968545b4full, 0x94778fea6faf9fdfull, 0x2b09dd7058ea4826ull, + 0x677cd9716de5c7bfull, 0x49d5214fffb2e6ddull, 0x0360e83a466b273cull, 0x1fc786af4f7b7691ull, + 0xa0b9d435783ea168ull, 0xd49f0c035f118cb6ull, 0x01205816c9d21d14ull, 0xac2453dd7d8f3d98ull, + 0x545217cc3f70aa64ull, 0x26b4028e9489c9c2ull, 0xdec2469fd6765e3eull, 0x04807d58036f7450ull, + 0xe5f17292823ddb45ull, 0xf30b569b024a5860ull, 0x62dcfc3fa758aefbull, 0xe84cad6c4e5e5aa1ull, + 0xccb81fce556ea94bull, 0x53b282ae7a74f908ull, 0x1b47fbf74c1402c1ull, 0x368eebf39828049full, + 0x7afbeff2ad278b06ull, 0xbe5e0a8cfe97caedull, 0xcfd8f7f413058e77ull, 0xf78b2bc301252c30ull, + 0x4d555c17fcdd928dull, 0x5f2f05467fc565f8ull, 0x24f4b2a21b30f3eaull, 0x860dd6bbecb768aaull, + 0x4c750401350f8f99ull, 0x0000000000000000ull, 0xecccd0344d312ef1ull, 0xb5231806be220571ull, + 0xc105c030990d28afull, 0x653c695de25cfd97ull, 0x159acc33c61ca419ull, 0xb89ec7f872418495ull, + 0xa9847693b73254dcull, 0x58cf90243ac13694ull, 0x59efc832f3132b80ull, 0x5c4fed7c39ae42c4ull, + 0x828dabe3efd81cfaull, 0xd13f294d95ace5f2ull, 0x7d1b7a90e823d86aull, 0xb643f03cf849224dull, + 0x3df3f979d89dcb03ull, 0x7426d836272f2ddeull, 0xdfe21e891fa4432aull, 0x3a136c1b9d99986full, + 0xfa36f43dcd46add4ull, 0xc025982650df35bbull, 0x856d3e81aadc4f96ull, 0xc4a5e57e53b041ebull, + 0x4708168b75ba4005ull, 0xaf44bbe73be41aa4ull, 0x971767d029c4b8e3ull, 0xb9be9feebb939981ull, + 0x215497ecd18d9aaeull, 0x316e7e91dd2c57f3ull, 0xcef8afe2dad79363ull, 0x3853dc371220a247ull, + 0x35ee03c9de4323a3ull, 0xe6919aa8c456fc79ull, 0xe05157dc4880b201ull, 0x7bdbb7e464f59612ull, + 0x127a59518318f775ull, 0x332ecebd52956ddbull, 0x8f30741d23bb9d1eull, 0xd922d3fd93720d52ull, + 0x7746300c61440ae2ull, 0x25d4eab4d2e2eefeull, 0x75068020eefd30caull, 0x135a01474acaea61ull, + 0x304e268714fe4ae7ull, 0xa519f17bb283c82cull, 0xdc82f6b359cf6416ull, 0x5baf781e7caa11a8ull, + 0xb2c38d64fb26561dull, 0x34ce5bdf17913eb7ull, 0x5d6fb56af07c5fd0ull, 0x182713cd0a7f25fdull, + 0x9e2ac576e6c84d57ull, 0x9aaab82ee5a73907ull, 0xa3d93c0f3e558654ull, 0x7e7b92aaae48ff56ull, + 0x872d8ead256575beull, 0x41c8dbfff96c0e7dull, 0x99ca5014a3cc1e3bull, 0x40e883e930be1369ull, + 0x1ca76e95091051adull, 0x4e35b42dbab6b5b1ull, 0x05a0254ecabd6944ull, 0xe1710fca8152af15ull, + 0xf22b0e8dcb984574ull, 0xb763a82a319b3f59ull, 0x63fca4296e8ab3efull, 0x9d4a2d4ca0a36a6bull, + 0xe331bfe60eeb953dull, 0xd5bf541596c391a2ull, 0xf5cb9bef8e9c1618ull, 0x46284e9dbc685d11ull, + 0x2074cffa185f87baull, 0xbd3ee2b6b8fcedd1ull, 0xae64e3f1f23607b0ull, 0xfeb68965ce29d984ull, + 0x55724fdaf6a2b770ull, 0x29496d5cd753720eull, 0xa75941573d3af204ull, 0x8e102c0bea69800aull, + 0x111ab16bc573d049ull, 0xd7ffe439197aab8aull, 0xefac380e0b5a09cdull, 0x48f579593660fbc9ull, + 0x22347fd697e6bd92ull, 0x61bc1405e13389c7ull, 0x4ab5c975b9d9c1e1ull, 0x80cd1bcf606126d2ull, + 0x7186fd78ed92449aull, 0x93971a882aabccb3ull, 0x88d0e17f66bfce72ull, 0x27945a985d5bd4d6ull + }, + { + 0xde553f8c05a811c8ull, 0x1906b59631b4f565ull, 0x436e70d6b1964ff7ull, 0x36d343cb8b1e9d85ull, + 0x843dfacc858aab5aull, 0xfdfc95c299bfc7f9ull, 0x0f634bdea1d51fa2ull, 0x6d458b3b76efb3cdull, + 0x85c3f77cf8593f80ull, 0x3c91315fbe737cb2ull, 0x2148b03366ace398ull, 0x18f8b8264c6761bfull, + 0xc830c1c495c9fb0full, 0x981a76102086a0aaull, 0xaa16012142f35760ull, 0x35cc54060c763cf6ull, + 0x42907d66cc45db2dull, 0x8203d44b965af4bcull, 0x3d6f3cefc3a0e868ull, 0xbc73ff69d292bda7ull, + 0x8722ed0102e20a29ull, 0x8f8185e8cd34deb7ull, 0x9b0561dda7ee01d9ull, 0x5335a0193227fad6ull, + 0xc9cecc74e81a6fd5ull, 0x54f5832e5c2431eaull, 0x99e47ba05d553470ull, 0xf7bee756acd226ceull, + 0x384e05a5571816fdull, 0xd1367452a47d0e6aull, 0xf29fde1c386ad85bull, 0x320c77316275f7caull, + 0xd0c879e2d9ae9ab0ull, 0xdb7406c69110ef5dull, 0x45505e51a2461011ull, 0xfc029872e46c5323ull, + 0xfa3cb6f5f7bc0cc5ull, 0x031f17cd8768a173ull, 0xbd8df2d9af41297dull, 0x9d3b4f5ab43e5e3full, + 0x4071671b36feee84ull, 0x716207e7d3e3b83dull, 0x48d20ff2f9283a1aull, 0x27769eb4757cbc7eull, + 0x5c56ebc793f2e574ull, 0xa48b474f9ef5dc18ull, 0x52cbada94ff46e0cull, 0x60c7da982d8199c6ull, + 0x0e9d466edc068b78ull, 0x4eec2175eaf865fcull, 0x550b8e9e21f7a530ull, 0x6b7ba5bc653fec2bull, + 0x5eb7f1ba6949d0ddull, 0x57ea94e3db4c9099ull, 0xf640eae6d101b214ull, 0xdd4a284182c0b0bbull, + 0xff1d8fbf6304f250ull, 0xb8accb933bf9d7e8ull, 0xe8867c478eb68c4dull, 0x3f8e2692391bddc1ull, + 0xcb2fd60912a15a7cull, 0xaec935dbab983d2full, 0xf55ffd2b56691367ull, 0x80e2ce366ce1c115ull, + 0x179bf3f8edb27e1dull, 0x01fe0db07dd394daull, 0xda8a0b76ecc37b87ull, 0x44ae53e1df9584cbull, + 0xb310b4b77347a205ull, 0xdfab323c787b8512ull, 0x3b511268d070b78eull, 0x65e6e3d2b9396753ull, + 0x6864b271e2574d58ull, 0x259784c98fc789d7ull, 0x02e11a7dfabb35a9ull, 0x8841a6dfa337158bull, + 0x7ade78c39b5dcdd0ull, 0xb7cf804d9a2cc84aull, 0x20b6bd831b7f7742ull, 0x75bd331d3a88d272ull, + 0x418f6aab4b2d7a5eull, 0xd9951cbb6babdaf4ull, 0xb6318dfde7ff5c90ull, 0x1f389b112264aa83ull, + 0x492c024284fbaec0ull, 0xe33a0363c608f9a0ull, 0x2688930408af28a4ull, 0xc7538a1a341ce4adull, + 0x5da8e677ee2171aeull, 0x8c9e92254a5c7fc4ull, 0x63d8cd55aae938b5ull, 0x29ebd8daa97a3706ull, + 0x959827b37be88aa1ull, 0x1484e4356adadf6eull, 0xa7945082199d7d6bull, 0xbf6ce8a455fa1cd4ull, + 0x9cc542eac9edcae5ull, 0x79c16f0e1c356ca3ull, 0x89bfab6fdee48151ull, 0xd4174d1830c5f0ffull, + 0x9258048415eb419dull, 0x6139d72850520d1cull, 0x6a85a80c18ec78f1ull, 0xcd11f88e0171059aull, + 0xcceff53e7ca29140ull, 0xd229639f2315af19ull, 0x90b91ef9ef507434ull, 0x5977d28d074a1be1ull, + 0x311360fce51d56b9ull, 0xc093a92d5a1f2f91ull, 0x1a19a25bb6dc5416ull, 0xeb996b8a09de2d3eull, + 0xfee3820f1ed7668aull, 0xd7085ad5b7ad518cull, 0x7fff41890fe53345ull, 0xec5948bd67dde602ull, + 0x2fd5f65dbaaa68e0ull, 0xa5754affe32648c2ull, 0xf8ddac880d07396cull, 0x6fa491468c548664ull, + 0x0c7c5c1326bdbed1ull, 0x4a33158f03930fb3ull, 0x699abfc19f84d982ull, 0xe4fa2054a80b329cull, + 0x6707f9af438252faull, 0x08a368e9cfd6d49eull, 0x47b1442c58fd25b8ull, 0xbbb3dc5ebc91769bull, + 0x1665fe489061eac7ull, 0x33f27a811fa66310ull, 0x93a609346838d547ull, 0x30ed6d4c98cec263ull, + 0x1dd9816cd8df9f2aull, 0x94662a03063b1e7bull, 0x83fdd9fbeb896066ull, 0x7b207573e68e590aull, + 0x5f49fc0a149a4407ull, 0x343259b671a5a82cull, 0xfbc2bb458a6f981full, 0xc272b350a0a41a38ull, + 0x3aaf1fd8ada32354ull, 0x6cbb868b0b3c2717ull, 0xa2b569c88d2583feull, 0xf180c9d1bf027928ull, + 0xaf37386bd64ba9f5ull, 0x12bacab2790a8088ull, 0x4c0d3b0810435055ull, 0xb2eeb9070e9436dfull, + 0xc5b29067cea7d104ull, 0xdcb425f1ff132461ull, 0x4f122cc5972bf126ull, 0xac282fa651230886ull, + 0xe7e537992f6393efull, 0xe61b3a2952b00735ull, 0x709c0a57ae302ce7ull, 0xe02514ae416058d3ull, + 0xc44c9dd7b37445deull, 0x5a68c5408022ba92ull, 0x1c278cdca50c0bf0ull, 0x6e5a9cf6f18712beull, + 0x86dce0b17f319ef3ull, 0x2d34ec2040115d49ull, 0x4bcd183f7e409b69ull, 0x2815d56ad4a9a3dcull, + 0x24698979f2141d0dull, 0x0000000000000000ull, 0x1ec696a15fb73e59ull, 0xd86b110b16784e2eull, + 0x8e7f8858b0e74a6dull, 0x063e2e8713d05fe6ull, 0xe2c40ed3bbdb6d7aull, 0xb1f1aeca89fc97acull, + 0xe1db191e3cb3cc09ull, 0x6418ee62c4eaf389ull, 0xc6ad87aa49cf7077ull, 0xd6f65765ca7ec556ull, + 0x9afb6c6dda3d9503ull, 0x7ce05644888d9236ull, 0x8d609f95378feb1eull, 0x23a9aa4e9c17d631ull, + 0x6226c0e5d73aac6full, 0x56149953a69f0443ull, 0xeeb852c09d66d3abull, 0x2b0ac2a753c102afull, + 0x07c023376e03cb3cull, 0x2ccae1903dc2c993ull, 0xd3d76e2f5ec63bc3ull, 0x9e2458973356ff4cull, + 0xa66a5d32644ee9b1ull, 0x0a427294356de137ull, 0x783f62be61e6f879ull, 0x1344c70204d91452ull, + 0x5b96c8f0fdf12e48ull, 0xa90916ecc59bf613ull, 0xbe92e5142829880eull, 0x727d102a548b194eull, + 0x1be7afebcb0fc0ccull, 0x3e702b2244c8491bull, 0xd5e940a84d166425ull, 0x66f9f41f3e51c620ull, + 0xabe80c913f20c3baull, 0xf07ec461c2d1edf2ull, 0xf361d3ac45b94c81ull, 0x0521394a94b8fe95ull, + 0xadd622162cf09c5cull, 0xe97871f7f3651897ull, 0xf4a1f09b2bba87bdull, 0x095d6559b2054044ull, + 0x0bbc7f2448be75edull, 0x2af4cf172e129675ull, 0x157ae98517094bb4ull, 0x9fda55274e856b96ull, + 0x914713499283e0eeull, 0xb952c623462a4332ull, 0x74433ead475b46a8ull, 0x8b5eb112245fb4f8ull, + 0xa34b6478f0f61724ull, 0x11a5dd7ffe6221fbull, 0xc16da49d27ccbb4bull, 0x76a224d0bde07301ull, + 0x8aa0bca2598c2022ull, 0x4df336b86d90c48full, 0xea67663a740db9e4ull, 0xef465f70e0b54771ull, + 0x39b008152acb8227ull, 0x7d1e5bf4f55e06ecull, 0x105bd0cf83b1b521ull, 0x775c2960c033e7dbull, + 0x7e014c397236a79full, 0x811cc386113255cfull, 0xeda7450d1a0e72d8ull, 0x5889df3d7a998f3bull, + 0x2e2bfbedc779fc3aull, 0xce0eef438619a4e9ull, 0x372d4e7bf6cd095full, 0x04df34fae96b6a4full, + 0xf923a13870d4adb6ull, 0xa1aa7e050a4d228dull, 0xa8f71b5cb84862c9ull, 0xb52e9a306097fde3ull, + 0x0d8251a35b6e2a0bull, 0x2257a7fee1c442ebull, 0x73831d9a29588d94ull, 0x51d4ba64c89ccf7full, + 0x502ab7d4b54f5ba5ull, 0x97793dce8153bf08ull, 0xe5042de4d5d8a646ull, 0x9687307efc802bd2ull, + 0xa05473b5779eb657ull, 0xb4d097801d446939ull, 0xcff0e2f3fbca3033ull, 0xc38cbee0dd778ee2ull, + 0x464f499c252eb162ull, 0xcad1dbb96f72cea6ull, 0xba4dd1eec142e241ull, 0xb00fa37af42f0376ull + }, + { + 0xcce4cd3aa968b245ull, 0x089d5484e80b7fafull, 0x638246c1b3548304ull, 0xd2fe0ec8c2355492ull, + 0xa7fbdf7ff2374eeeull, 0x4df1600c92337a16ull, 0x84e503ea523b12fbull, 0x0790bbfd53ab0c4aull, + 0x198a780f38f6ea9dull, 0x2ab30c8f55ec48cbull, 0xe0f7fed6b2c49db5ull, 0xb6ecf3f422cadbdcull, + 0x409c9a541358df11ull, 0xd3ce8a56dfde3fe3ull, 0xc3e9224312c8c1a0ull, 0x0d6dfa58816ba507ull, + 0xddf3e1b179952777ull, 0x04c02a42748bb1d9ull, 0x94c2abff9f2decb8ull, 0x4f91752da8f8acf4ull, + 0x78682befb169bf7bull, 0xe1c77a48af2ff6c4ull, 0x0c5d7ec69c80ce76ull, 0x4cc1e4928fd81167ull, + 0xfeed3d24d9997b62ull, 0x518bb6dfc3a54a23ull, 0x6dbf2d26151f9b90ull, 0xb5bc624b05ea664full, + 0xe86aaa525acfe21aull, 0x4801ced0fb53a0beull, 0xc91463e6c00868edull, 0x1027a815cd16fe43ull, + 0xf67069a0319204cdull, 0xb04ccc976c8abce7ull, 0xc0b9b3fc35e87c33ull, 0xf380c77c58f2de65ull, + 0x50bb3241de4e2152ull, 0xdf93f490435ef195ull, 0xf1e0d25d62390887ull, 0xaf668bfb1a3c3141ull, + 0xbc11b251f00a7291ull, 0x73a5eed47e427d47ull, 0x25bee3f6ee4c3b2eull, 0x43cc0beb34786282ull, + 0xc824e778dde3039cull, 0xf97d86d98a327728ull, 0xf2b043e24519b514ull, 0xe297ebf7880f4b57ull, + 0x3a94a49a98fab688ull, 0x868516cb68f0c419ull, 0xeffa11af0964ee50ull, 0xa4ab4ec0d517f37dull, + 0xa9c6b498547c567aull, 0x8e18424f80fbbbb6ull, 0x0bcdc53bcf2bc23cull, 0x137739aaea3643d0ull, + 0x2c1333ec1bac2ff0ull, 0x8d48d3f0a7db0625ull, 0x1e1ac3f26b5de6d7ull, 0xf520f81f16b2b95eull, + 0x9f0f6ec450062e84ull, 0x0130849e1deb6b71ull, 0xd45e31ab8c7533a9ull, 0x652279a2fd14e43full, + 0x3209f01e70f1c927ull, 0xbe71a770cac1a473ull, 0x0e3d6be7a64b1894ull, 0x7ec8148cff29d840ull, + 0xcb7476c7fac3be0full, 0x72956a4a63a91636ull, 0x37f95ec21991138full, 0x9e3fea5a4ded45f5ull, + 0x7b38ba50964902e8ull, 0x222e580bbde73764ull, 0x61e253e0899f55e6ull, 0xfc8d2805e352ad80ull, + 0x35994be3235ac56dull, 0x09add01af5e014deull, 0x5e8659a6780539c6ull, 0xb17c48097161d796ull, + 0x026015213acbd6e2ull, 0xd1ae9f77e515e901ull, 0xb7dc776a3f21b0adull, 0xaba6a1b96eb78098ull, + 0x9bcf4486248d9f5dull, 0x582666c536455efdull, 0xfdbdac9bfeb9c6f1ull, 0xc47999be4163cdeaull, + 0x765540081722a7efull, 0x3e548ed8ec710751ull, 0x3d041f67cb51bac2ull, 0x7958af71ac82d40aull, + 0x36c9da5c047a78feull, 0xed9a048e33af38b2ull, 0x26ee7249c96c86bdull, 0x900281bdeba65d61ull, + 0x11172c8bd0fd9532ull, 0xea0abf73600434f8ull, 0x42fc8f75299309f3ull, 0x34a9cf7d3eb1ae1cull, + 0x2b838811480723baull, 0x5ce64c8742ceef24ull, 0x1adae9b01fd6570eull, 0x3c349bf9d6bad1b3ull, + 0x82453c891c7b75c0ull, 0x97923a40b80d512bull, 0x4a61dbf1c198765cull, 0xb48ce6d518010d3eull, + 0xcfb45c858e480fd6ull, 0xd933cbf30d1e96aeull, 0xd70ea014ab558e3aull, 0xc189376228031742ull, + 0x9262949cd16d8b83ull, 0xeb3a3bed7def5f89ull, 0x49314a4ee6b8cbcfull, 0xdcc3652f647e4c06ull, + 0xda635a4c2a3e2b3dull, 0x470c21a940f3d35bull, 0x315961a157d174b4ull, 0x6672e81dda3459acull, + 0x5b76f77a1165e36eull, 0x445cb01667d36ec8ull, 0xc5491d205c88a69bull, 0x456c34887a3805b9ull, + 0xffddb9bac4721013ull, 0x99af51a71e4649bfull, 0xa15be01cbc7729d5ull, 0x52db2760e485f7b0ull, + 0x8c78576eba306d54ull, 0xae560f6507d75a30ull, 0x95f22f6182c687c9ull, 0x71c5fbf54489aba5ull, + 0xca44f259e728d57eull, 0x88b87d2ccebbdc8dull, 0xbab18d32be4a15aaull, 0x8be8ec93e99b611eull, + 0x17b713e89ebdf209ull, 0xb31c5d284baa0174ull, 0xeeca9531148f8521ull, 0xb8d198138481c348ull, + 0x8988f9b2d350b7fcull, 0xb9e11c8d996aa839ull, 0x5a4673e40c8e881full, 0x1687977683569978ull, + 0xbf4123eed72acf02ull, 0x4ea1f1b3b513c785ull, 0xe767452be16f91ffull, 0x7505d1b730021a7cull, + 0xa59bca5ec8fc980cull, 0xad069eda20f7e7a3ull, 0x38f4b1bba231606aull, 0x60d2d77e94743e97ull, + 0x9affc0183966f42cull, 0x248e6768f3a7505full, 0xcdd449a4b483d934ull, 0x87b59255751baf68ull, + 0x1bea6d2e023d3c7full, 0x6b1f12455b5ffcabull, 0x743555292de9710dull, 0xd8034f6d10f5fddfull, + 0xc6198c9f7ba81b08ull, 0xbb8109aca3a17edbull, 0xfa2d1766ad12cabbull, 0xc729080166437079ull, + 0x9c5fff7b77269317ull, 0x0000000000000000ull, 0x15d706c9a47624ebull, 0x6fdf38072fd44d72ull, + 0x5fb6dd3865ee52b7ull, 0xa33bf53d86bcff37ull, 0xe657c1b5fc84fa8eull, 0xaa962527735cebe9ull, + 0x39c43525bfda0b1bull, 0x204e4d2a872ce186ull, 0x7a083ece8ba26999ull, 0x554b9c9db72efbfaull, + 0xb22cd9b656416a05ull, 0x96a2bedea5e63a5aull, 0x802529a826b0a322ull, 0x8115ad363b5bc853ull, + 0x8375b81701901eb1ull, 0x3069e53f4a3a1fc5ull, 0xbd2136cfede119e0ull, 0x18bafc91251d81ecull, + 0x1d4a524d4c7d5b44ull, 0x05f0aedc6960daa8ull, 0x29e39d3072ccf558ull, 0x70f57f6b5962c0d4ull, + 0x989fd53903ad22ceull, 0xf84d024797d91c59ull, 0x547b1803aac5908bull, 0xf0d056c37fd263f6ull, + 0xd56eb535919e58d8ull, 0x1c7ad6d351963035ull, 0x2e7326cd2167f912ull, 0xac361a443d1c8cd2ull, + 0x697f076461942a49ull, 0x4b515f6fdc731d2dull, 0x8ad8680df4700a6full, 0x41ac1eca0eb3b460ull, + 0x7d988533d80965d3ull, 0xa8f6300649973d0bull, 0x7765c4960ac9cc9eull, 0x7ca801adc5e20ea2ull, + 0xdea3700e5eb59ae4ull, 0xa06b6482a19c42a4ull, 0x6a2f96db46b497daull, 0x27def6d7d487edccull, + 0x463ca5375d18b82aull, 0xa6cb5be1efdc259full, 0x53eba3fef96e9cc1ull, 0xce84d81b93a364a7ull, + 0xf4107c810b59d22full, 0x333974806d1aa256ull, 0x0f0def79bba073e5ull, 0x231edc95a00c5c15ull, + 0xe437d494c64f2c6cull, 0x91320523f64d3610ull, 0x67426c83c7df32ddull, 0x6eefbc99323f2603ull, + 0x9d6f7be56acdf866ull, 0x5916e25b2bae358cull, 0x7ff89012e2c2b331ull, 0x035091bf2720bd93ull, + 0x561b0d22900e4669ull, 0x28d319ae6f279e29ull, 0x2f43a2533c8c9263ull, 0xd09e1be9f8fe8270ull, + 0xf740ed3e2c796fbcull, 0xdb53ded237d5404cull, 0x62b2c25faebfe875ull, 0x0afd41a5d2c0a94dull, + 0x6412fd3ce0ff8f4eull, 0xe3a76f6995e42026ull, 0x6c8fa9b808f4f0e1ull, 0xc2d9a6dd0f23aad1ull, + 0x8f28c6d19d10d0c7ull, 0x85d587744fd0798aull, 0xa20b71a39b579446ull, 0x684f83fa7c7f4138ull, + 0xe507500adba4471dull, 0x3f640a46f19a6c20ull, 0x1247bd34f7dd28a1ull, 0x2d23b77206474481ull, + 0x93521002cc86e0f2ull, 0x572b89bc8de52d18ull, 0xfb1d93f8b0f9a1caull, 0xe95a2ecc4724896bull, + 0x3ba420048511ddf9ull, 0xd63e248ab6bee54bull, 0x5dd6c8195f258455ull, 0x06a03f634e40673bull, + 0x1f2a476c76b68da6ull, 0x217ec9b49ac78af7ull, 0xecaa80102e4453c3ull, 0x14e78257b99d4f9aull + }, + { + 0x20329b2cc87bba05ull, 0x4f5eb6f86546a531ull, 0xd4f44775f751b6b1ull, 0x8266a47b850dfa8bull, + 0xbb986aa15a6ca985ull, 0xc979eb08f9ae0f99ull, 0x2da6f447a2375ea1ull, 0x1e74275dcd7d8576ull, + 0xbc20180a800bc5f8ull, 0xb4a2f701b2dc65beull, 0xe726946f981b6d66ull, 0x48e6c453bf21c94cull, + 0x42cad9930f0a4195ull, 0xefa47b64aacccd20ull, 0x71180a8960409a42ull, 0x8bb3329bf6a44e0cull, + 0xd34c35de2d36daccull, 0xa92f5b7cbc23dc96ull, 0xb31a85aa68bb09c3ull, 0x13e04836a73161d2ull, + 0xb24dfc4129c51d02ull, 0x8ae44b70b7da5acdull, 0xe671ed84d96579a7ull, 0xa4bb3417d66f3832ull, + 0x4572ab38d56d2de8ull, 0xb1b47761ea47215cull, 0xe81c09cf70aba15dull, 0xffbdb872ce7f90acull, + 0xa8782297fd5dc857ull, 0x0d946f6b6a4ce4a4ull, 0xe4df1f4f5b995138ull, 0x9ebc71edca8c5762ull, + 0x0a2c1dc0b02b88d9ull, 0x3b503c115d9d7b91ull, 0xc64376a8111ec3a2ull, 0xcec199a323c963e4ull, + 0xdc76a87ec58616f7ull, 0x09d596e073a9b487ull, 0x14583a9d7d560dafull, 0xf4c6dc593f2a0cb4ull, + 0xdd21d19584f80236ull, 0x4a4836983ddde1d3ull, 0xe58866a41ae745f9ull, 0xf591a5b27e541875ull, + 0x891dc05074586693ull, 0x5b068c651810a89eull, 0xa30346bc0c08544full, 0x3dbf3751c684032dull, + 0x2a1e86ec785032dcull, 0xf73f5779fca830eaull, 0xb60c05ca30204d21ull, 0x0cc316802b32f065ull, + 0x8770241bdd96be69ull, 0xb861e18199ee95dbull, 0xf805cad91418fcd1ull, 0x29e70dccbbd20e82ull, + 0xc7140f435060d763ull, 0x0f3a9da0e8b0cc3bull, 0xa2543f574d76408eull, 0xbd7761e1c175d139ull, + 0x4b1f4f737ca3f512ull, 0x6dc2df1f2fc137abull, 0xf1d05c3967b14856ull, 0xa742bf3715ed046cull, + 0x654030141d1697edull, 0x07b872abda676c7dull, 0x3ce84eba87fa17ecull, 0xc1fb0403cb79afdfull, + 0x3e46bc7105063f73ull, 0x278ae987121cd678ull, 0xa1adb4778ef47cd0ull, 0x26dd906c5362c2b9ull, + 0x05168060589b44e2ull, 0xfbfc41f9d79ac08full, 0x0e6de44ba9ced8faull, 0x9feb08068bf243a3ull, + 0x7b341749d06b129bull, 0x229c69e74a87929aull, 0xe09ee6c4427c011bull, 0x5692e30e725c4c3aull, + 0xda99a33e5e9f6e4bull, 0x353dd85af453a36bull, 0x25241b4c90e0fee7ull, 0x5de987258309d022ull, + 0xe230140fc0802984ull, 0x93281e86a0c0b3c6ull, 0xf229d719a4337408ull, 0x6f6c2dd4ad3d1f34ull, + 0x8ea5b2fbae3f0aeeull, 0x8331dd90c473ee4aull, 0x346aa1b1b52db7aaull, 0xdf8f235e06042aa9ull, + 0xcc6f6b68a1354b7bull, 0x6c95a6f46ebf236aull, 0x52d31a856bb91c19ull, 0x1a35ded6d498d555ull, + 0xf37eaef2e54d60c9ull, 0x72e181a9a3c2a61cull, 0x98537aad51952fdeull, 0x16f6c856ffaa2530ull, + 0xd960281e9d1d5215ull, 0x3a0745fa1ce36f50ull, 0x0b7b642bf1559c18ull, 0x59a87eae9aec8001ull, + 0x5e100c05408bec7cull, 0x0441f98b19e55023ull, 0xd70dcc5534d38aefull, 0x927f676de1bea707ull, + 0x9769e70db925e3e5ull, 0x7a636ea29115065aull, 0x468b201816ef11b6ull, 0xab81a9b73edff409ull, + 0xc0ac7de88a07bb1eull, 0x1f235eb68c0391b7ull, 0x6056b074458dd30full, 0xbe8eeac102f7ed67ull, + 0xcd381283e04b5fbaull, 0x5cbefecec277c4e3ull, 0xd21b4c356c48ce0dull, 0x1019c31664b35d8cull, + 0x247362a7d19eea26ull, 0xebe582efb3299d03ull, 0x02aef2cb82fc289full, 0x86275df09ce8aaa8ull, + 0x28b07427faac1a43ull, 0x38a9b7319e1f47cfull, 0xc82e92e3b8d01b58ull, 0x06ef0b409b1978bcull, + 0x62f842bfc771fb90ull, 0x9904034610eb3b1full, 0xded85ab5477a3e68ull, 0x90d195a663428f98ull, + 0x5384636e2ac708d8ull, 0xcbd719c37b522706ull, 0xae9729d76644b0ebull, 0x7c8c65e20a0c7ee6ull, + 0x80c856b007f1d214ull, 0x8c0b40302cc32271ull, 0xdbcedad51fe17a8aull, 0x740e8ae938dbdea0ull, + 0xa615c6dc549310adull, 0x19cc55f6171ae90bull, 0x49b1bdb8fe5fdd8dull, 0xed0a89af2830e5bfull, + 0x6a7aadb4f5a65bd6ull, 0x7e22972988f05679ull, 0xf952b3325566e810ull, 0x39fecedadf61530eull, + 0x6101c99f04f3c7ceull, 0x2e5f7f6761b562ffull, 0xf08725d226cf5c97ull, 0x63af3b54860fef51ull, + 0x8ff2cb10ef411e2full, 0x884ab9bb35267252ull, 0x4df04433e7ba8daeull, 0x9afd8866d3690741ull, + 0x66b9bb34de94abb3ull, 0x9baaf18d92171380ull, 0x543c11c5f0a064a5ull, 0x17a1b1bdbed431f1ull, + 0xb5f58eeaf3a2717full, 0xc355f6c849858740ull, 0xec5df044694ef17eull, 0xd83751f5dc6346d4ull, + 0xfc4433520dfdacf2ull, 0x0000000000000000ull, 0x5a51f58e596ebc5full, 0x3285aaf12e34cf16ull, + 0x8d5c39db6dbd36b0ull, 0x12b731dde64f7513ull, 0x94906c2d7aa7dfbbull, 0x302b583aacc8e789ull, + 0x9d45facd090e6b3cull, 0x2165e2c78905aec4ull, 0x68d45f7f775a7349ull, 0x189b2c1d5664fdcaull, + 0xe1c99f2f030215daull, 0x6983269436246788ull, 0x8489af3b1e148237ull, 0xe94b702431d5b59cull, + 0x33d2d31a6f4adbd7ull, 0xbfd9932a4389f9a6ull, 0xb0e30e8aab39359dull, 0xd1e2c715afcaf253ull, + 0x150f43763c28196eull, 0xc4ed846393e2eb3dull, 0x03f98b20c3823c5eull, 0xfd134ab94c83b833ull, + 0x556b682eb1de7064ull, 0x36c4537a37d19f35ull, 0x7559f30279a5ca61ull, 0x799ae58252973a04ull, + 0x9c12832648707ffdull, 0x78cd9c6913e92ec5ull, 0x1d8dac7d0effb928ull, 0x439da0784e745554ull, + 0x413352b3cc887dcbull, 0xbacf134a1b12bd44ull, 0x114ebafd25cd494dull, 0x2f08068c20cb763eull, + 0x76a07822ba27f63full, 0xeab2fb04f25789c2ull, 0xe3676de481fe3d45ull, 0x1b62a73d95e6c194ull, + 0x641749ff5c68832cull, 0xa5ec4dfc97112cf3ull, 0xf6682e92bdd6242bull, 0x3f11c59a44782bb2ull, + 0x317c21d1edb6f348ull, 0xd65ab5be75ad9e2eull, 0x6b2dd45fb4d84f17ull, 0xfaab381296e4d44eull, + 0xd0b5befeeeb4e692ull, 0x0882ef0b32d7a046ull, 0x512a91a5a83b2047ull, 0x963e9ee6f85bf724ull, + 0x4e09cf132438b1f0ull, 0x77f701c9fb59e2feull, 0x7ddb1c094b726a27ull, 0x5f4775ee01f5f8bdull, + 0x9186ec4d223c9b59ull, 0xfeeac1998f01846dull, 0xac39db1ce4b89874ull, 0xb75b7c21715e59e0ull, + 0xafc0503c273aa42aull, 0x6e3b543fec430bf5ull, 0x704f7362213e8e83ull, 0x58ff0745db9294c0ull, + 0x67eec2df9feabf72ull, 0xa0facd9ccf8a6811ull, 0xb936986ad890811aull, 0x95c715c63bd9cb7aull, + 0xca8060283a2c33c7ull, 0x507de84ee9453486ull, 0x85ded6d05f6a96f6ull, 0x1cdad5964f81ade9ull, + 0xd5a33e9eb62fa270ull, 0x40642b588df6690aull, 0x7f75eec2c98e42b8ull, 0x2cf18dace3494a60ull, + 0x23cb100c0bf9865bull, 0xeef3028febb2d9e1ull, 0x4425d2d394133929ull, 0xaad6d05c7fa1e0c8ull, + 0xad6ea2f7a5c68cb5ull, 0xc2028f2308fb9381ull, 0x819f2f5b468fc6d5ull, 0xc5bafd88d29cfffcull, + 0x47dc59f357910577ull, 0x2b49ff07392e261dull, 0x57c59ae5332258fbull, 0x73b6f842e2bcb2ddull, + 0xcf96e04862b77725ull, 0x4ca73dd8a6c4996full, 0x015779eb417e14c1ull, 0x37932a9176af8bf4ull + }, + { + 0x190a2c9b249df23eull, 0x2f62f8b62263e1e9ull, 0x7a7f754740993655ull, 0x330b7ba4d5564d9full, + 0x4c17a16a46672582ull, 0xb22f08eb7d05f5b8ull, 0x535f47f40bc148ccull, 0x3aec5d27d4883037ull, + 0x10ed0a1825438f96ull, 0x516101f72c233d17ull, 0x13cc6f949fd04eaeull, 0x739853c441474bfdull, + 0x653793d90d3f5b1bull, 0x5240647b96b0fc2full, 0x0c84890ad27623e0ull, 0xd7189b32703aaea3ull, + 0x2685de3523bd9c41ull, 0x99317c5b11bffefaull, 0x0d9baa854f079703ull, 0x70b93648fbd48ac5ull, + 0xa80441fce30bc6beull, 0x7287704bdc36ff1eull, 0xb65384ed33dc1f13ull, 0xd36417343ee34408ull, + 0x39cd38ab6e1bf10full, 0x5ab861770a1f3564ull, 0x0ebacf09f594563bull, 0xd04572b884708530ull, + 0x3cae9722bdb3af47ull, 0x4a556b6f2f5cbaf2ull, 0xe1704f1f76c4bd74ull, 0x5ec4ed7144c6dfcfull, + 0x16afc01d4c7810e6ull, 0x283f113cd629ca7aull, 0xaf59a8761741ed2dull, 0xeed5a3991e215facull, + 0x3bf37ea849f984d4ull, 0xe413e096a56ce33cull, 0x2c439d3a98f020d1ull, 0x637559dc6404c46bull, + 0x9e6c95d1e5f5d569ull, 0x24bb9836045fe99aull, 0x44efa466dac8ecc9ull, 0xc6eab2a5c80895d6ull, + 0x803b50c035220cc4ull, 0x0321658cba93c138ull, 0x8f9ebc465dc7ee1cull, 0xd15a5137190131d3ull, + 0x0fa5ec8668e5e2d8ull, 0x91c979578d1037b1ull, 0x0642ca05693b9f70ull, 0xefca80168350eb4full, + 0x38d21b24f36a45ecull, 0xbeab81e1af73d658ull, 0x8cbfd9cae7542f24ull, 0xfd19cc0d81f11102ull, + 0x0ac6430fbb4dbc90ull, 0x1d76a09d6a441895ull, 0x2a01573ff1cbbfa1ull, 0xb572e161894fde2bull, + 0x8124734fa853b827ull, 0x614b1fdf43e6b1b0ull, 0x68ac395c4238cc18ull, 0x21d837bfd7f7b7d2ull, + 0x20c714304a860331ull, 0x5cfaab726324aa14ull, 0x74c5ba4eb50d606eull, 0xf3a3030474654739ull, + 0x23e671bcf015c209ull, 0x45f087e947b9582aull, 0xd8bd77b418df4c7bull, 0xe06f6c90ebb50997ull, + 0x0bd96080263c0873ull, 0x7e03f9410e40dcfeull, 0xb8e94be4c6484928ull, 0xfb5b0608e8ca8e72ull, + 0x1a2b49179e0e3306ull, 0x4e29e76961855059ull, 0x4f36c4e6fcf4e4baull, 0x49740ee395cf7bcaull, + 0xc2963ea386d17f7dull, 0x90d65ad810618352ull, 0x12d34c1b02a1fa4dull, 0xfa44258775bb3a91ull, + 0x18150f14b9ec46ddull, 0x1491861e6b9a653dull, 0x9a1019d7ab2c3fc2ull, 0x3668d42d06fe13d7ull, + 0xdcc1fbb25606a6d0ull, 0x969490dd795a1c22ull, 0x3549b1a1bc6dd2efull, 0xc94f5e23a0ed770eull, + 0xb9f6686b5b39fdcbull, 0xc4d4f4a6efeae00dull, 0xe732851a1fff2204ull, 0x94aad6de5eb869f9ull, + 0x3f8ff2ae07206e7full, 0xfe38a9813b62d03aull, 0xa7a1ad7a8bee2466ull, 0x7b6056c8dde882b6ull, + 0x302a1e286fc58ca7ull, 0x8da0fa457a259bc7ull, 0xb3302b64e074415bull, 0x5402ae7eff8b635full, + 0x08f8050c9cafc94bull, 0xae468bf98a3059ceull, 0x88c355cca98dc58full, 0xb10e6d67c7963480ull, + 0xbad70de7e1aa3cf3ull, 0xbfb4a26e320262bbull, 0xcb711820870f02d5ull, 0xce12b7a954a75c9dull, + 0x563ce87dd8691684ull, 0x9f73b65e7884618aull, 0x2b1e74b06cba0b42ull, 0x47cec1ea605b2df1ull, + 0x1c698312f735ac76ull, 0x5fdbcefed9b76b2cull, 0x831a354c8fb1cdfcull, 0x820516c312c0791full, + 0xb74ca762aeadabf0ull, 0xfc06ef821c80a5e1ull, 0x5723cbf24518a267ull, 0x9d4df05d5f661451ull, + 0x588627742dfd40bfull, 0xda8331b73f3d39a0ull, 0x17b0e392d109a405ull, 0xf965400bcf28fba9ull, + 0x7c3dbf4229a2a925ull, 0x023e460327e275dbull, 0x6cd0b55a0ce126b3ull, 0xe62da695828e96e7ull, + 0x42ad6e63b3f373b9ull, 0xe50cc319381d57dfull, 0xc5cbd729729b54eeull, 0x46d1e265fd2a9912ull, + 0x6428b056904eeff8ull, 0x8be23040131e04b7ull, 0x6709d5da2add2ec0ull, 0x075de98af44a2b93ull, + 0x8447dcc67bfbe66full, 0x6616f655b7ac9a23ull, 0xd607b8bded4b1a40ull, 0x0563af89d3a85e48ull, + 0x3db1b4ad20c21ba4ull, 0x11f22997b8323b75ull, 0x292032b34b587e99ull, 0x7f1cdace9331681dull, + 0x8e819fc9c0b65affull, 0xa1e3677fe2d5bb16ull, 0xcd33d225ee349da5ull, 0xd9a2543b85aef898ull, + 0x795e10cbfa0af76dull, 0x25a4bbb9992e5d79ull, 0x78413344677b438eull, 0xf0826688cef68601ull, + 0xd27b34bba392f0ebull, 0x551d8df162fad7bcull, 0x1e57c511d0d7d9adull, 0xdeffbdb171e4d30bull, + 0xf4feea8e802f6caaull, 0xa480c8f6317de55eull, 0xa0fc44f07fa40ff5ull, 0x95b5f551c3c9dd1aull, + 0x22f952336d6476eaull, 0x0000000000000000ull, 0xa6be8ef5169f9085ull, 0xcc2cf1aa73452946ull, + 0x2e7ddb39bf12550aull, 0xd526dd3157d8db78ull, 0x486b2d6c08becf29ull, 0x9b0f3a58365d8b21ull, + 0xac78cdfaadd22c15ull, 0xbc95c7e28891a383ull, 0x6a927f5f65dab9c3ull, 0xc3891d2c1ba0cb9eull, + 0xeaa92f9f50f8b507ull, 0xcf0d9426c9d6e87eull, 0xca6e3baf1a7eb636ull, 0xab25247059980786ull, + 0x69b31ad3df4978fbull, 0xe2512a93cc577c4cull, 0xff278a0ea61364d9ull, 0x71a615c766a53e26ull, + 0x89dc764334fc716cull, 0xf87a638452594f4aull, 0xf2bc208be914f3daull, 0x8766b94ac1682757ull, + 0xbbc82e687cdb8810ull, 0x626a7a53f9757088ull, 0xa2c202f358467a2eull, 0x4d0882e5db169161ull, + 0x09e7268301de7da8ull, 0xe897699c771ac0dcull, 0xc8507dac3d9cc3edull, 0xc0a878a0a1330aa6ull, + 0x978bb352e42ba8c1ull, 0xe9884a13ea6b743full, 0x279afdbabecc28a2ull, 0x047c8c064ed9eaabull, + 0x507e2278b15289f4ull, 0x599904fbb08cf45cull, 0xbd8ae46d15e01760ull, 0x31353da7f2b43844ull, + 0x8558ff49e68a528cull, 0x76fbfc4d92ef15b5ull, 0x3456922e211c660cull, 0x86799ac55c1993b4ull, + 0x3e90d1219a51da9cull, 0x2d5cbeb505819432ull, 0x982e5fd48cce4a19ull, 0xdb9c1238a24c8d43ull, + 0xd439febecaa96f9bull, 0x418c0bef0960b281ull, 0x158ea591f6ebd1deull, 0x1f48e69e4da66d4eull, + 0x8afd13cf8e6fb054ull, 0xf5e1c9011d5ed849ull, 0xe34e091c5126c8afull, 0xad67ee7530a398f6ull, + 0x43b24dec2e82c75aull, 0x75da99c1287cd48dull, 0x92e81cdb3783f689ull, 0xa3dd217cc537cecdull, + 0x60543c50de970553ull, 0x93f73f54aaf2426aull, 0xa91b62737e7a725dull, 0xf19d4507538732e2ull, + 0x77e4dfc20f9ea156ull, 0x7d229ccdb4d31dc6ull, 0x1b346a98037f87e5ull, 0xedf4c615a4b29e94ull, + 0x4093286094110662ull, 0xb0114ee85ae78063ull, 0x6ff1d0d6b672e78bull, 0x6dcf96d591909250ull, + 0xdfe09e3eec9567e8ull, 0x3214582b4827f97cull, 0xb46dc2ee143e6ac8ull, 0xf6c0ac8da7cd1971ull, + 0xebb60c10cd8901e4ull, 0xf7df8f023abcad92ull, 0x9c52d3d2c217a0b2ull, 0x6b8d5cd0f8ab0d20ull, + 0x3777f7a29b8fa734ull, 0x011f238f9d71b4e3ull, 0xc1b75b2f3c42be45ull, 0x5de588fdfe551ef7ull, + 0x6eeef3592b035368ull, 0xaa3a07ffc4e9b365ull, 0xecebe59a39c32a77ull, 0x5ba742f8976e8187ull, + 0x4b4a48e0b22d0e11ull, 0xddded83dcb771233ull, 0xa59feb79ac0c51bdull, 0xc7f5912a55792135ull + }, + { + 0x6d6ae04668a9b08aull, 0x3ab3f04b0be8c743ull, 0xe51e166b54b3c908ull, 0xbe90a9eb35c2f139ull, + 0xb2c7066637f2bec1ull, 0xaa6945613392202cull, 0x9a28c36f3b5201ebull, 0xddce5a93ab536994ull, + 0x0e34133ef6382827ull, 0x52a02ba1ec55048bull, 0xa2f88f97c4b2a177ull, 0x8640e513ca2251a5ull, + 0xcdf1d36258137622ull, 0xfe6cb708dedf8ddbull, 0x8a174a9ec8121e5dull, 0x679896036b81560eull, + 0x59ed033395795feeull, 0x1dd778ab8b74edafull, 0xee533ef92d9f926dull, 0x2a8c79baf8a8d8f5ull, + 0x6bcf398e69b119f6ull, 0xe20491742fafdd95ull, 0x276488e0809c2aecull, 0xea955b82d88f5cceull, + 0x7102c63a99d9e0c4ull, 0xf9763017a5c39946ull, 0x429fa2501f151b3dull, 0x4659c72bea05d59eull, + 0x984b7fdccf5a6634ull, 0xf742232953fbb161ull, 0x3041860e08c021c7ull, 0x747bfd9616cd9386ull, + 0x4bb1367192312787ull, 0x1b72a1638a6c44d3ull, 0x4a0e68a6e8359a66ull, 0x169a5039f258b6caull, + 0xb98a2ef44edee5a4ull, 0xd9083fe85e43a737ull, 0x967f6ce239624e13ull, 0x8874f62d3c1a7982ull, + 0x3c1629830af06e3full, 0x9165ebfd427e5a8eull, 0xb5dd81794ceeaa5cull, 0x0de8f15a7834f219ull, + 0x70bd98ede3dd5d25ull, 0xaccc9ca9328a8950ull, 0x56664eda1945ca28ull, 0x221db34c0f8859aeull, + 0x26dbd637fa98970dull, 0x1acdffb4f068f932ull, 0x4585254f64090fa0ull, 0x72de245e17d53afaull, + 0x1546b25d7c546cf4ull, 0x207e0ffffb803e71ull, 0xfaaad2732bcf4378ull, 0xb462dfae36ea17bdull, + 0xcf926fd1ac1b11fdull, 0xe0672dc7dba7ba4aull, 0xd3fa49ad5d6b41b3ull, 0x8ba81449b216a3bcull, + 0x14f9ec8a0650d115ull, 0x40fc1ee3eb1d7ce2ull, 0x23a2ed9b758ce44full, 0x782c521b14fddc7eull, + 0x1c68267cf170504eull, 0xbcf31558c1ca96e6ull, 0xa781b43b4ba6d235ull, 0xf6fd7dfe29ff0c80ull, + 0xb0a4bad5c3fad91eull, 0xd199f51ea963266cull, 0x414340349119c103ull, 0x5405f269ed4dadf7ull, + 0xabd61bb649969dcdull, 0x6813dbeae7bdc3c8ull, 0x65fb2ab09f8931d1ull, 0xf1e7fae152e3181dull, + 0xc1a67cef5a2339daull, 0x7a4feea8e0f5bba1ull, 0x1e0b9acf05783791ull, 0x5b8ebf8061713831ull, + 0x80e53cdbcb3af8d9ull, 0x7e898bd315e57502ull, 0xc6bcfbf0213f2d47ull, 0x95a38e86b76e942dull, + 0x092e94218d243cbaull, 0x8339debf453622e7ull, 0xb11be402b9fe64ffull, 0x57d9100d634177c9ull, + 0xcc4e8db52217cbc3ull, 0x3b0cae9c71ec7aa2ull, 0xfb158ca451cbfe99ull, 0x2b33276d82ac6514ull, + 0x01bf5ed77a04bde1ull, 0xc5601994af33f779ull, 0x75c4a3416cc92e67ull, 0xf3844652a6eb7fc2ull, + 0x3487e375fdd0ef64ull, 0x18ae430704609eedull, 0x4d14efb993298efbull, 0x815a620cb13e4538ull, + 0x125c354207487869ull, 0x9eeea614ce42cf48ull, 0xce2d3106d61fac1cull, 0xbbe99247bad6827bull, + 0x071a871f7b1c149dull, 0x2e4a1cc10db81656ull, 0x77a71ff298c149b8ull, 0x06a5d9c80118a97cull, + 0xad73c27e488e34b1ull, 0x443a7b981e0db241ull, 0xe3bbcfa355ab6074ull, 0x0af276450328e684ull, + 0x73617a896dd1871bull, 0x58525de4ef7de20full, 0xb7be3dcab8e6cd83ull, 0x19111dd07e64230cull, + 0x842359a03e2a367aull, 0x103f89f1f3401fb6ull, 0xdc710444d157d475ull, 0xb835702334da5845ull, + 0x4320fc876511a6dcull, 0xd026abc9d3679b8dull, 0x17250eee885c0b2bull, 0x90dab52a387ae76full, + 0x31fed8d972c49c26ull, 0x89cba8fa461ec463ull, 0x2ff5421677bcabb7ull, 0x396f122f85e41d7dull, + 0xa09b332430bac6a8ull, 0xc888e8ced7070560ull, 0xaeaf201ac682ee8full, 0x1180d7268944a257ull, + 0xf058a43628e7a5fcull, 0xbd4c4b8fbbce2b07ull, 0xa1246df34abe7b49ull, 0x7d5569b79be9af3cull, + 0xa9b5a705bd9efa12ull, 0xdb6b835baa4bc0e8ull, 0x05793bac8f147342ull, 0x21c1512881848390ull, + 0xfdb0556c50d357e5ull, 0x613d4fcb6a99ff72ull, 0x03dce2648e0cda3eull, 0xe949b9e6568386f0ull, + 0xfc0f0bbb2ad7ea04ull, 0x6a70675913b5a417ull, 0x7f36d5046fe1c8e3ull, 0x0c57af8d02304ff8ull, + 0x32223abdfcc84618ull, 0x0891caf6f720815bull, 0xa63eeaec31a26fd4ull, 0x2507345374944d33ull, + 0x49d28ac266394058ull, 0xf5219f9aa7f3d6beull, 0x2d96fea583b4cc68ull, 0x5a31e1571b7585d0ull, + 0x8ed12fe53d02d0feull, 0xdfade6205f5b0e4bull, 0x4cabb16ee92d331aull, 0x04c6657bf510cea3ull, + 0xd73c2cd6a87b8f10ull, 0xe1d87310a1a307abull, 0x6cd5be9112ad0d6bull, 0x97c032354366f3f2ull, + 0xd4e0ceb22677552eull, 0x0000000000000000ull, 0x29509bde76a402cbull, 0xc27a9e8bd42fe3e4ull, + 0x5ef7842cee654b73ull, 0xaf107ecdbc86536eull, 0x3fcacbe784fcb401ull, 0xd55f90655c73e8cfull, + 0xe6c2f40fdabf1336ull, 0xe8f6e7312c873b11ull, 0xeb2a0555a28be12full, 0xe4a148bc2eb774e9ull, + 0x9b979db84156bc0aull, 0x6eb60222e6a56ab4ull, 0x87ffbbc4b026ec44ull, 0xc703a5275b3b90a6ull, + 0x47e699fc9001687full, 0x9c8d1aa73a4aa897ull, 0x7cea3760e1ed12ddull, 0x4ec80ddd1d2554c5ull, + 0x13e36b957d4cc588ull, 0x5d2b66486069914dull, 0x92b90999cc7280b0ull, 0x517cc9c56259deb5ull, + 0xc937b619ad03b881ull, 0xec30824ad997f5b2ull, 0xa45d565fc5aa080bull, 0xd6837201d27f32f1ull, + 0x635ef3789e9198adull, 0x531f75769651b96aull, 0x4f77530a6721e924ull, 0x486dd4151c3dfdb9ull, + 0x5f48dafb9461f692ull, 0x375b011173dc355aull, 0x3da9775470f4d3deull, 0x8d0dcd81b30e0ac0ull, + 0x36e45fc609d888bbull, 0x55baacbe97491016ull, 0x8cb29356c90ab721ull, 0x76184125e2c5f459ull, + 0x99f4210bb55edbd5ull, 0x6f095cf59ca1d755ull, 0x9f51f8c3b44672a9ull, 0x3538bda287d45285ull, + 0x50c39712185d6354ull, 0xf23b1885dcefc223ull, 0x79930ccc6ef9619full, 0xed8fdc9da3934853ull, + 0xcb540aaa590bdf5eull, 0x5c94389f1a6d2cacull, 0xe77daad8a0bbaed7ull, 0x28efc5090ca0bf2aull, + 0xbf2ff73c4fc64cd8ull, 0xb37858b14df60320ull, 0xf8c96ec0dfc724a7ull, 0x828680683f329f06ull, + 0x941cd051cd6a29ccull, 0xc3c5c05cae2b5e05ull, 0xb601631dc2e27062ull, 0xc01922382027843bull, + 0x24b86a840e90f0d2ull, 0xd245177a276ffc52ull, 0x0f8b4de98c3c95c6ull, 0x3e759530fef809e0ull, + 0x0b4d2892792c5b65ull, 0xc4df4743d5374a98ull, 0xa5e20888bfaeb5eaull, 0xba56cc90c0d23f9aull, + 0x38d04cf8ffe0a09cull, 0x62e1adafe495254cull, 0x0263bcb3f40867dfull, 0xcaeb547d230f62bfull, + 0x6082111c109d4293ull, 0xdad4dd8cd04f7d09ull, 0xefec602e579b2f8cull, 0x1fb4c4187f7c8a70ull, + 0xffd3e9dfa4db303aull, 0x7bf0b07f9af10640ull, 0xf49ec14dddf76b5full, 0x8f6e713247066d1full, + 0x339d646a86ccfbf9ull, 0x64447467e58d8c30ull, 0x2c29a072f9b07189ull, 0xd8b7613f24471ad6ull, + 0x6627c8d41185ebefull, 0xa347d140beb61c96ull, 0xde12b8f7255fb3aaull, 0x9d324470404e1576ull, + 0x9306574eb6763d51ull, 0xa80af9d2c79a47f3ull, 0x859c0777442e8b9bull, 0x69ac853d9db97e29ull + }, + { + 0xc3407dfc2de6377eull, 0x5b9e93eea4256f77ull, 0xadb58fdd50c845e0ull, 0x5219ff11a75bed86ull, + 0x356b61cfd90b1de9ull, 0xfb8f406e25abe037ull, 0x7a5a0231c0f60796ull, 0x9d3cd216e1f5020bull, + 0x0c6550fb6b48d8f3ull, 0xf57508c427ff1c62ull, 0x4ad35ffa71cb407dull, 0x6290a2da1666aa6dull, + 0xe284ec2349355f9full, 0xb3c307c53d7c84ecull, 0x05e23c0468365a02ull, 0x190bac4d6c9ebfa8ull, + 0x94bbbee9e28b80faull, 0xa34fc777529cb9b5ull, 0xcc7b39f095bcd978ull, 0x2426addb0ce532e3ull, + 0x7e79329312ce4fc7ull, 0xab09a72eebec2917ull, 0xf8d15499f6b9d6c2ull, 0x1a55b8babf8c895dull, + 0xdb8add17fb769a85ull, 0xb57f2f368658e81bull, 0x8acd36f18f3f41f6ull, 0x5ce3b7bba50f11d3ull, + 0x114dcc14d5ee2f0aull, 0xb91a7fcded1030e8ull, 0x81d5425fe55de7a1ull, 0xb6213bc1554adeeeull, + 0x80144ef95f53f5f2ull, 0x1e7688186db4c10cull, 0x3b912965db5fe1bcull, 0xc281715a97e8252dull, + 0x54a5d7e21c7f8171ull, 0x4b12535ccbc5522eull, 0x1d289cefbea6f7f9ull, 0x6ef5f2217d2e729eull, + 0xe6a7dc819b0d17ceull, 0x1b94b41c05829b0eull, 0x33d7493c622f711eull, 0xdcf7f942fa5ce421ull, + 0x600fba8b7f7a8ecbull, 0x46b60f011a83988eull, 0x235b898e0dcf4c47ull, 0x957ab24f588592a9ull, + 0x4354330572b5c28cull, 0xa5f3ef84e9b8d542ull, 0x8c711e02341b2d01ull, 0x0b1874ae6a62a657ull, + 0x1213d8e306fc19ffull, 0xfe6d7c6a4d9dba35ull, 0x65ed868f174cd4c9ull, 0x88522ea0e6236550ull, + 0x899322065c2d7703ull, 0xc01e690bfef4018bull, 0x915982ed8abddaf8ull, 0xbe675b98ec3a4e4cull, + 0xa996bf7f82f00db1ull, 0xe1daf8d49a27696aull, 0x2effd5d3dc8986e7ull, 0xd153a51f2b1a2e81ull, + 0x18caa0ebd690adfbull, 0x390e3134b243c51aull, 0x2778b92cdff70416ull, 0x029f1851691c24a6ull, + 0x5e7cafeacc133575ull, 0xfa4e4cc89fa5f264ull, 0x5a5f9f481e2b7d24ull, 0x484c47ab18d764dbull, + 0x400a27f2a1a7f479ull, 0xaeeb9b2a83da7315ull, 0x721c626879869734ull, 0x042330a2d2384851ull, + 0x85f672fd3765aff0ull, 0xba446b3a3e02061dull, 0x73dd6ecec3888567ull, 0xffac70ccf793a866ull, + 0xdfa9edb5294ed2d4ull, 0x6c6aea7014325638ull, 0x834a5a0e8c41c307ull, 0xcdba35562fb2cb2bull, + 0x0ad97808d06cb404ull, 0x0f3b440cb85aee06ull, 0xe5f9c876481f213bull, 0x98deee1289c35809ull, + 0x59018bbfcd394bd1ull, 0xe01bf47220297b39ull, 0xde68e1139340c087ull, 0x9fa3ca4788e926adull, + 0xbb85679c840c144eull, 0x53d8f3b71d55ffd5ull, 0x0da45c5dd146caa0ull, 0x6f34fe87c72060cdull, + 0x57fbc315cf6db784ull, 0xcee421a1fca0fddeull, 0x3d2d0196607b8d4bull, 0x642c8a29ad42c69aull, + 0x14aff010bdd87508ull, 0xac74837beac657b3ull, 0x3216459ad821634dull, 0x3fb219c70967a9edull, + 0x06bc28f3bb246cf7ull, 0xf2082c9126d562c6ull, 0x66b39278c45ee23cull, 0xbd394f6f3f2878b9ull, + 0xfd33689d9e8f8cc0ull, 0x37f4799eb017394full, 0x108cc0b26fe03d59ull, 0xda4bd1b1417888d6ull, + 0xb09d1332ee6eb219ull, 0x2f3ed975668794b4ull, 0x58c0871977375982ull, 0x7561463d78ace990ull, + 0x09876cff037e82f1ull, 0x7fb83e35a8c05d94ull, 0x26b9b58a65f91645ull, 0xef20b07e9873953full, + 0x3148516d0b3355b8ull, 0x41cb2b541ba9e62aull, 0x790416c613e43163ull, 0xa011d380818e8f40ull, + 0x3a5025c36151f3efull, 0xd57095bdf92266d0ull, 0x498d4b0da2d97688ull, 0x8b0c3a57353153a5ull, + 0x21c491df64d368e1ull, 0x8f2f0af5e7091bf4ull, 0x2da1c1240f9bb012ull, 0xc43d59a92ccc49daull, + 0xbfa6573e56345c1full, 0x828b56a8364fd154ull, 0x9a41f643e0df7cafull, 0xbcf843c985266aeaull, + 0x2b1de9d7b4bfdce5ull, 0x20059d79dedd7ab2ull, 0x6dabe6d6ae3c446bull, 0x45e81bf6c991ae7bull, + 0x6351ae7cac68b83eull, 0xa432e32253b6c711ull, 0xd092a9b991143cd2ull, 0xcac711032e98b58full, + 0xd8d4c9e02864ac70ull, 0xc5fc550f96c25b89ull, 0xd7ef8dec903e4276ull, 0x67729ede7e50f06full, + 0xeac28c7af045cf3dull, 0xb15c1f945460a04aull, 0x9cfddeb05bfb1058ull, 0x93c69abce3a1fe5eull, + 0xeb0380dc4a4bdd6eull, 0xd20db1e8f8081874ull, 0x229a8528b7c15e14ull, 0x44291750739fbc28ull, + 0xd3ccbd4e42060a27ull, 0xf62b1c33f4ed2a97ull, 0x86a8660ae4779905ull, 0xd62e814a2a305025ull, + 0x477703a7a08d8addull, 0x7b9b0e977af815c5ull, 0x78c51a60a9ea2330ull, 0xa6adfb733aaae3b7ull, + 0x97e5aa1e3199b60full, 0x0000000000000000ull, 0xf4b404629df10e31ull, 0x5564db44a6719322ull, + 0x9207961a59afec0dull, 0x9624a6b88b97a45cull, 0x363575380a192b1cull, 0x2c60cd82b595a241ull, + 0x7d272664c1dc7932ull, 0x7142769faa94a1c1ull, 0xa1d0df263b809d13ull, 0x1630e841d4c451aeull, + 0xc1df65ad44fa13d8ull, 0x13d2d445bcf20bacull, 0xd915c546926abe23ull, 0x38cf3d92084dd749ull, + 0xe766d0272103059dull, 0xc7634d5effde7f2full, 0x077d2455012a7ea4ull, 0xedbfa82ff16fb199ull, + 0xaf2a978c39d46146ull, 0x42953fa3c8bbd0dfull, 0xcb061da59496a7dcull, 0x25e7a17db6eb20b0ull, + 0x34aa6d6963050fbaull, 0xa76cf7d580a4f1e4ull, 0xf7ea10954ee338c4ull, 0xfcf2643b24819e93ull, + 0xcf252d0746aeef8dull, 0x4ef06f58a3f3082cull, 0x563acfb37563a5d7ull, 0x5086e740ce47c920ull, + 0x2982f186dda3f843ull, 0x87696aac5e798b56ull, 0x5d22bb1d1f010380ull, 0x035e14f7d31236f5ull, + 0x3cec0d30da759f18ull, 0xf3c920379cdb7095ull, 0xb8db736b571e22bbull, 0xdd36f5e44052f672ull, + 0xaac8ab8851e23b44ull, 0xa857b3d938fe1fe2ull, 0x17f1e4e76eca43fdull, 0xec7ea4894b61a3caull, + 0x9e62c6e132e734feull, 0xd4b1991b432c7483ull, 0x6ad6c283af163acfull, 0x1ce9904904a8e5aaull, + 0x5fbda34c761d2726ull, 0xf910583f4cb7c491ull, 0xc6a241f845d06d7cull, 0x4f3163fe19fd1a7full, + 0xe99c988d2357f9c8ull, 0x8eee06535d0709a7ull, 0x0efa48aa0254fc55ull, 0xb4be23903c56fa48ull, + 0x763f52caabbedf65ull, 0xeee1bcd8227d876cull, 0xe345e085f33b4dccull, 0x3e731561b369bbbeull, + 0x2843fd2067adea10ull, 0x2adce5710eb1ceb6ull, 0xb7e03767ef44ccbdull, 0x8db012a48e153f52ull, + 0x61ceb62dc5749c98ull, 0xe85d942b9959eb9bull, 0x4c6f7709caef2c8aull, 0x84377e5b8d6bbda3ull, + 0x30895dcbb13d47ebull, 0x74a04a9bc2a2fbc3ull, 0x6b17ce251518289cull, 0xe438c4d0f2113368ull, + 0x1fb784bed7bad35full, 0x9b80fae55ad16efcull, 0x77fe5e6c11b0cd36ull, 0xc858095247849129ull, + 0x08466059b97090a2ull, 0x01c10ca6ba0e1253ull, 0x6988d6747c040c3aull, 0x6849dad2c60a1e69ull, + 0x5147ebe67449db73ull, 0xc99905f4fd8a837aull, 0x991fe2b433cd4a5aull, 0xf09734c04fc94660ull, + 0xa28ecbd1e892abe6ull, 0xf1563866f5c75433ull, 0x4dae7baf70e13ed9ull, 0x7ce62ac27bd26b61ull, + 0x70837a39109ab392ull, 0x90988e4b30b3c8abull, 0xb2020b63877296bfull, 0x156efcb607d6675bull + }, + { + 0xe63f55ce97c331d0ull, 0x25b506b0015bba16ull, 0xc8706e29e6ad9ba8ull, 0x5b43d3775d521f6aull, + 0x0bfa3d577035106eull, 0xab95fc172afb0e66ull, 0xf64b63979e7a3276ull, 0xf58b4562649dad4bull, + 0x48f7c3dbae0c83f1ull, 0xff31916642f5c8c5ull, 0xcbb048dc1c4a0495ull, 0x66b8f83cdf622989ull, + 0x35c130e908e2b9b0ull, 0x7c761a61f0b34fa1ull, 0x3601161cf205268dull, 0x9e54ccfe2219b7d6ull, + 0x8b7d90a538940837ull, 0x9cd403588ea35d0bull, 0xbc3c6fea9ccc5b5aull, 0xe5ff733b6d24aeedull, + 0xceed22de0f7eb8d2ull, 0xec8581cab1ab545eull, 0xb96105e88ff8e71dull, 0x8ca03501871a5eadull, + 0x76ccce65d6db2a2full, 0x5883f582a7b58057ull, 0x3f7be4ed2e8adc3eull, 0x0fe7be06355cd9c9ull, + 0xee054e6c1d11be83ull, 0x1074365909b903a6ull, 0x5dde9f80b4813c10ull, 0x4a770c7d02b6692cull, + 0x5379c8d5d7809039ull, 0xb4067448161ed409ull, 0x5f5e5026183bd6cdull, 0xe898029bf4c29df9ull, + 0x7fb63c940a54d09cull, 0xc5171f897f4ba8bcull, 0xa6f28db7b31d3d72ull, 0x2e4f3be7716eaa78ull, + 0x0d6771a099e63314ull, 0x82076254e41bf284ull, 0x2f0fd2b42733df98ull, 0x5c9e76d3e2dc49f0ull, + 0x7aeb569619606cdbull, 0x83478b07b2468764ull, 0xcfadcb8d5923cd32ull, 0x85dac7f05b95a41eull, + 0xb5469d1b4043a1e9ull, 0xb821ecbbd9a592fdull, 0x1b8e0b0e798c13c8ull, 0x62a57b6d9a0be02eull, + 0xfcf1b793b81257f8ull, 0x9d94ea0bd8fe28ebull, 0x4cea408aeb654a56ull, 0x23284a47e888996cull, + 0x2d8f1d128b893545ull, 0xf4cbac3132c0d8abull, 0xbd7c86b9ca912ebaull, 0x3a268eef3dbe6079ull, + 0xf0d62f6077a9110cull, 0x2735c916ade150cbull, 0x89fd5f03942ee2eaull, 0x1acee25d2fd16628ull, + 0x90f39bab41181bffull, 0x430dfe8cde39939full, 0xf70b8ac4c8274796ull, 0x1c53aeaac6024552ull, + 0x13b410acf35e9c9bull, 0xa532ab4249faa24full, 0x2b1251e5625a163full, 0xd7e3e676da4841c7ull, + 0xa7b264e4e5404892ull, 0xda8497d643ae72d3ull, 0x861ae105a1723b23ull, 0x38a6414991048aa4ull, + 0x6578dec92585b6b4ull, 0x0280cfa6acbaeaddull, 0x88bdb650c273970aull, 0x9333bd5ebbff84c2ull, + 0x4e6a8f2c47dfa08bull, 0x321c954db76cef2aull, 0x418d312a72837942ull, 0xb29b38bfffcdf773ull, + 0x6c022c38f90a4c07ull, 0x5a033a240b0f6a8aull, 0x1f93885f3ce5da6full, 0xc38a537e96988bc6ull, + 0x39e6a81ac759ff44ull, 0x29929e43cee0fce2ull, 0x40cdd87924de0ca2ull, 0xe9d8ebc8a29fe819ull, + 0x0c2798f3cfbb46f4ull, 0x55e484223e53b343ull, 0x4650948ecd0d2fd8ull, 0x20e86cb2126f0651ull, + 0x6d42c56baf5739e7ull, 0xa06fc1405ace1e08ull, 0x7babbfc54f3d193bull, 0x424d17df8864e67full, + 0xd8045870ef14980eull, 0xc6d7397c85ac3781ull, 0x21a885e1443273b1ull, 0x67f8116f893f5c69ull, + 0x24f5efe35706cff6ull, 0xd56329d076f2ab1aull, 0x5e1eb9754e66a32dull, 0x28d2771098bd8902ull, + 0x8f6013f47dfdc190ull, 0x17a993fdb637553cull, 0xe0a219397e1012aaull, 0x786b9930b5da8606ull, + 0x6e82e39e55b0a6daull, 0x875a0856f72f4ec3ull, 0x3741ff4fa458536dull, 0xac4859b3957558fcull, + 0x7ef6d5c75c09a57cull, 0xc04a758b6c7f14fbull, 0xf9acdd91ab26ebbfull, 0x7391a467c5ef9668ull, + 0x335c7c1ee1319acaull, 0xa91533b18641e4bbull, 0xe4bf9a683b79db0dull, 0x8e20faa72ba0b470ull, + 0x51f907737b3a7ae4ull, 0x2268a314bed5ec8cull, 0xd944b123b949edeeull, 0x31dcb3b84d8b7017ull, + 0xd3fe65279f218860ull, 0x097af2f1dc8ffab3ull, 0x9b09a6fc312d0b91ull, 0xcc6ded78a3c4520full, + 0x3481d9ba5ebfcc50ull, 0x4f2a667f1182d56bull, 0xdfd9fdd4509ace94ull, 0x26752045fbbc252bull, + 0xbffc491f662bc467ull, 0xdd593272fc202449ull, 0x3cbbc218d46d4303ull, 0x91b372f817456e1full, + 0x681faf69bc6385a0ull, 0xb686bbeebaa43ed4ull, 0x1469b5084cd0ca01ull, 0x98c98009cbca94acull, + 0x6438379a73d8c354ull, 0xc2caba2dc0c5fe26ull, 0x3e3b0dbe78d7a9deull, 0x50b9ee202d670f04ull, + 0x4590b27b37eab0e5ull, 0x6025b4cb36b10af3ull, 0xfb2c1237079c0162ull, 0xa12f28130c936be8ull, + 0x4b37e52e54eb1cccull, 0x083a1ba28ad28f53ull, 0xc10a9cd83a22611bull, 0x9f1425ad7444c236ull, + 0x069d4cf7e9d3237aull, 0xedc56899e7f621beull, 0x778c273680865fcfull, 0x309c5aeb1bd605f7ull, + 0x8de0dc52d1472b4dull, 0xf8ec34c2fd7b9e5full, 0xea18cd3d58787724ull, 0xaad515447ca67b86ull, + 0x9989695a9d97e14cull, 0x0000000000000000ull, 0xf196c63321f464ecull, 0x71116bc169557cb5ull, + 0xaf887f466f92c7c1ull, 0x972e3e0ffe964d65ull, 0x190ec4a8d536f915ull, 0x95aef1a9522ca7b8ull, + 0xdc19db21aa7d51a9ull, 0x94ee18fa0471d258ull, 0x8087adf248a11859ull, 0xc457f6da2916dd5cull, + 0xfa6cfb6451c17482ull, 0xf256e0c6db13fbd1ull, 0x6a9f60cf10d96f7dull, 0x4daaa9d9bd383fb6ull, + 0x03c026f5fae79f3dull, 0xde99148706c7bb74ull, 0x2a52b8b6340763dfull, 0x6fc20acd03edd33aull, + 0xd423c08320afdefaull, 0xbbe1ca4e23420dc0ull, 0x966ed75ca8cb3885ull, 0xeb58246e0e2502c4ull, + 0x055d6a021334bc47ull, 0xa47242111fa7d7afull, 0xe3623fcc84f78d97ull, 0x81c744a11efc6db9ull, + 0xaec8961539cfb221ull, 0xf31609958d4e8e31ull, 0x63e5923ecc5695ceull, 0x47107ddd9b505a38ull, + 0xa3afe7b5a0298135ull, 0x792b7063e387f3e6ull, 0x0140e953565d75e0ull, 0x12f4f9ffa503e97bull, + 0x750ce8902c3cb512ull, 0xdbc47e8515f30733ull, 0x1ed3610c6ab8af8full, 0x5239218681dde5d9ull, + 0xe222d69fd2aaf877ull, 0xfe71783514a8bd25ull, 0xcaf0a18f4a177175ull, 0x61655d9860ec7f13ull, + 0xe77fbc9dc19e4430ull, 0x2ccff441ddd440a5ull, 0x16e97aaee06a20dcull, 0xa855dae2d01c915bull, + 0x1d1347f9905f30b2ull, 0xb7c652bdecf94b34ull, 0xd03e43d265c6175dull, 0xfdb15ec0ee4f2218ull, + 0x57644b8492e9599eull, 0x07dda5a4bf8e569aull, 0x54a46d71680ec6a3ull, 0x5624a2d7c4b42c7eull, + 0xbebca04c3076b187ull, 0x7d36f332a6ee3a41ull, 0x3b6667bc6be31599ull, 0x695f463aea3ef040ull, + 0xad08b0e0c3282d1cull, 0xb15b1e4a052a684eull, 0x44d05b2861b7c505ull, 0x15295c5b1a8dbfe1ull, + 0x744c01c37a61c0f2ull, 0x59c31cd1f1e8f5b7ull, 0xef45a73f4b4ccb63ull, 0x6bdf899c46841a9dull, + 0x3dfb2b4b823036e3ull, 0xa2ef0ee6f674f4d5ull, 0x184e2dfb836b8cf5ull, 0x1134df0a5fe47646ull, + 0xbaa1231d751f7820ull, 0xd17eaa81339b62bdull, 0xb01bf71953771daeull, 0x849a2ea30dc8d1feull, + 0x705182923f080955ull, 0x0ea757556301ac29ull, 0x041d83514569c9a7ull, 0x0abad4042668658eull, + 0x49b72a88f851f611ull, 0x8a3d79f66ec97dd7ull, 0xcd2d042bf59927efull, 0xc930877ab0f0ee48ull, + 0x9273540deda2f122ull, 0xc797d02fd3f14261ull, 0xe1e2f06a284d674aull, 0xd2be8c74c97cfd80ull, + 0x9a494faf67707e71ull, 0xb3dbd1eca9908293ull, 0x72d14d3493b2e388ull, 0xd6a30f258c153427ull + } +}; + +template +const uint64_t streebog_constants::RC[12][8] = { + { 0xdd806559f2a64507ull, 0x05767436cc744d23ull, 0xa2422a08a460d315ull, 0x4b7ce09192676901ull, + 0x714eb88d7585c4fcull, 0x2f6a76432e45d016ull, 0xebcb2f81c0657c1full, 0xb1085bda1ecadae9ull }, + { 0xe679047021b19bb7ull, 0x55dda21bd7cbcd56ull, 0x5cb561c2db0aa7caull, 0x9ab5176b12d69958ull, + 0x61d55e0f16b50131ull, 0xf3feea720a232b98ull, 0x4fe39d460f70b5d7ull, 0x6fa3b58aa99d2f1aull }, + { 0x991e96f50aba0ab2ull, 0xc2b6f443867adb31ull, 0xc1c93a376062db09ull, 0xd3e20fe490359eb1ull, + 0xf2ea7514b1297b7bull, 0x06f15e5f529c1f8bull, 0x0a39fc286a3d8435ull, 0xf574dcac2bce2fc7ull }, + { 0x220cbebc84e3d12eull, 0x3453eaa193e837f1ull, 0xd8b71333935203beull, 0xa9d72c82ed03d675ull, + 0x9d721cad685e353full, 0x488e857e335c3c7dull, 0xf948e1a05d71e4ddull, 0xef1fdfb3e81566d2ull }, + { 0x601758fd7c6cfe57ull, 0x7a56a27ea9ea63f5ull, 0xdfff00b723271a16ull, 0xbfcd1747253af5a3ull, + 0x359e35d7800fffbdull, 0x7f151c1f1686104aull, 0x9a3f410c6ca92363ull, 0x4bea6bacad474799ull }, + { 0xfa68407a46647d6eull, 0xbf71c57236904f35ull, 0x0af21f66c2bec6b6ull, 0xcffaa6b71c9ab7b4ull, + 0x187f9ab49af08ec6ull, 0x2d66c4f95142a46cull, 0x6fa4c33b7a3039c0ull, 0xae4faeae1d3ad3d9ull }, + { 0x8886564d3a14d493ull, 0x3517454ca23c4af3ull, 0x06476983284a0504ull, 0x0992abc52d822c37ull, + 0xd3473e33197a93c9ull, 0x399ec6c7e6bf87c9ull, 0x51ac86febf240954ull, 0xf4c70e16eeaac5ecull }, + { 0xa47f0dd4bf02e71eull, 0x36acc2355951a8d9ull, 0x69d18d2bd1a5c42full, 0xf4892bcb929b0690ull, + 0x89b4443b4ddbc49aull, 0x4eb7f8719c36de1eull, 0x03e7aa020c6e4141ull, 0x9b1f5b424d93c9a7ull }, + { 0x7261445183235adbull, 0x0e38dc92cb1f2a60ull, 0x7b2b8a9aa6079c54ull, 0x800a440bdbb2ceb1ull, + 0x3cd955b7e00d0984ull, 0x3a7d3a1b25894224ull, 0x944c9ad8ec165fdeull, 0x378f5a541631229bull }, + { 0x74b4c7fb98459cedull, 0x3698fad1153bb6c3ull, 0x7a1e6c303b7652f4ull, 0x9fe76702af69334bull, + 0x1fffe18a1b336103ull, 0x8941e71cff8a78dbull, 0x382ae548b2e4f3f3ull, 0xabbedea680056f52ull }, + { 0x6bcaa4cd81f32d1bull, 0xdea2594ac06fd85dull, 0xefbacd1d7d476e98ull, 0x8a1d71efea48b9caull, + 0x2001802114846679ull, 0xd8fa6bbbebab0761ull, 0x3002c6cd635afe94ull, 0x7bcd9ed0efc889fbull }, + { 0x48bc924af11bd720ull, 0xfaf417d5d9b21b99ull, 0xe71da4aa88e12852ull, 0x5d80ef9d1891cc86ull, + 0xf82012d430219f9bull, 0xcda43c32bcdf1d77ull, 0xd21380b00449b17aull, 0x378ee767f11631baull } +}; + + +} // namespace detail + +} // namespace digestpp + +#endif \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/detail/constants/whirlpool_constants.hpp b/ext/include/digestpp/algorithm/detail/constants/whirlpool_constants.hpp new file mode 100644 index 0000000..87e9e09 --- /dev/null +++ b/ext/include/digestpp/algorithm/detail/constants/whirlpool_constants.hpp @@ -0,0 +1,571 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_PROVIDERS_WHIRLPOOL_CONSTANTS_HPP +#define DIGESTPP_PROVIDERS_WHIRLPOOL_CONSTANTS_HPP + +namespace digestpp +{ + +namespace detail +{ + +template +struct whirlpool_constants +{ + static const uint64_t RC[10]; + static const uint64_t T[8][256]; +}; + +template +const uint64_t whirlpool_constants::RC[10] = { + 0x4f01b887e8c62318ull, + 0x52916f79f5d2a636ull, + 0x357b0ca38e9bbc60ull, + 0x57fe4b2ec2d7e01dull, + 0xda4af09fe5377715ull, + 0x856ba0b10a29c958ull, + 0x67053ecbf4105dbdull, + 0xd8957da78b4127e4ull, + 0x9e4717dd667ceefbull, + 0x33835aad07bf2dcaull +}; + +template +const uint64_t whirlpool_constants::T[8][256] = { + { + 0xd83078c018601818ull, 0x2646af05238c2323ull, 0xb891f97ec63fc6c6ull, 0xfbcd6f13e887e8e8ull, + 0xcb13a14c87268787ull, 0x116d62a9b8dab8b8ull, 0x0902050801040101ull, 0x0d9e6e424f214f4full, + 0x9b6ceead36d83636ull, 0xff510459a6a2a6a6ull, 0x0cb9bdded26fd2d2ull, 0x0ef706fbf5f3f5f5ull, + 0x96f280ef79f97979ull, 0x30dece5f6fa16f6full, 0x6d3feffc917e9191ull, 0xf8a407aa52555252ull, + 0x47c0fd27609d6060ull, 0x35657689bccabcbcull, 0x372bcdac9b569b9bull, 0x8a018c048e028e8eull, + 0xd25b1571a3b6a3a3ull, 0x6c183c600c300c0cull, 0x84f68aff7bf17b7bull, 0x806ae1b535d43535ull, + 0xf53a69e81d741d1dull, 0xb3dd4753e0a7e0e0ull, 0x21b3acf6d77bd7d7ull, 0x9c99ed5ec22fc2c2ull, + 0x435c966d2eb82e2eull, 0x29967a624b314b4bull, 0x5de121a3fedffefeull, 0xd5ae168257415757ull, + 0xbd2a41a815541515ull, 0xe8eeb69f77c17777ull, 0x926eeba537dc3737ull, 0x9ed7567be5b3e5e5ull, + 0x1323d98c9f469f9full, 0x23fd17d3f0e7f0f0ull, 0x20947f6a4a354a4aull, 0x44a9959eda4fdadaull, + 0xa2b025fa587d5858ull, 0xcf8fca06c903c9c9ull, 0x7c528d5529a42929ull, 0x5a1422500a280a0aull, + 0x507f4fe1b1feb1b1ull, 0xc95d1a69a0baa0a0ull, 0x14d6da7f6bb16b6bull, 0xd917ab5c852e8585ull, + 0x3c677381bdcebdbdull, 0x8fba34d25d695d5dull, 0x9020508010401010ull, 0x07f503f3f4f7f4f4ull, + 0xdd8bc016cb0bcbcbull, 0xd37cc6ed3ef83e3eull, 0x2d0a112805140505ull, 0x78cee61f67816767ull, + 0x97d55373e4b7e4e4ull, 0x024ebb25279c2727ull, 0x7382583241194141ull, 0xa70b9d2c8b168b8bull, + 0xf6530151a7a6a7a7ull, 0xb2fa94cf7de97d7dull, 0x4937fbdc956e9595ull, 0x56ad9f8ed847d8d8ull, + 0x70eb308bfbcbfbfbull, 0xcdc17123ee9feeeeull, 0xbbf891c77ced7c7cull, 0x71cce31766856666ull, + 0x7ba78ea6dd53ddddull, 0xaf2e4bb8175c1717ull, 0x458e460247014747ull, 0x1a21dc849e429e9eull, + 0xd489c51eca0fcacaull, 0x585a99752db42d2dull, 0x2e637991bfc6bfbfull, 0x3f0e1b38071c0707ull, + 0xac472301ad8eadadull, 0xb0b42fea5a755a5aull, 0xef1bb56c83368383ull, 0xb666ff8533cc3333ull, + 0x5cc6f23f63916363ull, 0x12040a1002080202ull, 0x93493839aa92aaaaull, 0xdee2a8af71d97171ull, + 0xc68dcf0ec807c8c8ull, 0xd1327dc819641919ull, 0x3b92707249394949ull, 0x5faf9a86d943d9d9ull, + 0x31f91dc3f2eff2f2ull, 0xa8db484be3abe3e3ull, 0xb9b62ae25b715b5bull, 0xbc0d9234881a8888ull, + 0x3e29c8a49a529a9aull, 0x0b4cbe2d26982626ull, 0xbf64fa8d32c83232ull, 0x597d4ae9b0fab0b0ull, + 0xf2cf6a1be983e9e9ull, 0x771e33780f3c0f0full, 0x33b7a6e6d573d5d5ull, 0xf41dba74803a8080ull, + 0x27617c99bec2bebeull, 0xeb87de26cd13cdcdull, 0x8968e4bd34d03434ull, 0x3290757a483d4848ull, + 0x54e324abffdbffffull, 0x8df48ff77af57a7aull, 0x643deaf4907a9090ull, 0x9dbe3ec25f615f5full, + 0x3d40a01d20802020ull, 0x0fd0d56768bd6868ull, 0xca3472d01a681a1aull, 0xb7412c19ae82aeaeull, + 0x7d755ec9b4eab4b4ull, 0xcea8199a544d5454ull, 0x7f3be5ec93769393ull, 0x2f44aa0d22882222ull, + 0x63c8e907648d6464ull, 0x2aff12dbf1e3f1f1ull, 0xcce6a2bf73d17373ull, 0x82245a9012481212ull, + 0x7a805d3a401d4040ull, 0x4810284008200808ull, 0x959be856c32bc3c3ull, 0xdfc57b33ec97ececull, + 0x4dab9096db4bdbdbull, 0xc05f1f61a1bea1a1ull, 0x9107831c8d0e8d8dull, 0xc87ac9f53df43d3dull, + 0x5b33f1cc97669797ull, 0x0000000000000000ull, 0xf983d436cf1bcfcfull, 0x6e5687452bac2b2bull, + 0xe1ecb39776c57676ull, 0xe619b06482328282ull, 0x28b1a9fed67fd6d6ull, 0xc33677d81b6c1b1bull, + 0x74775bc1b5eeb5b5ull, 0xbe432911af86afafull, 0x1dd4df776ab56a6aull, 0xeaa00dba505d5050ull, + 0x578a4c1245094545ull, 0x38fb18cbf3ebf3f3ull, 0xad60f09d30c03030ull, 0xc4c3742bef9befefull, + 0xda7ec3e53ffc3f3full, 0xc7aa1c9255495555ull, 0xdb591079a2b2a2a2ull, 0xe9c96503ea8feaeaull, + 0x6acaec0f65896565ull, 0x036968b9bad2babaull, 0x4a5e93652fbc2f2full, 0x8e9de74ec027c0c0ull, + 0x60a181bede5fdedeull, 0xfc386ce01c701c1cull, 0x46e72ebbfdd3fdfdull, 0x1f9a64524d294d4dull, + 0x7639e0e492729292ull, 0xfaeabc8f75c97575ull, 0x360c1e3006180606ull, 0xae0998248a128a8aull, + 0x4b7940f9b2f2b2b2ull, 0x85d15963e6bfe6e6ull, 0x7e1c36700e380e0eull, 0xe73e63f81f7c1f1full, + 0x55c4f73762956262ull, 0x3ab5a3eed477d4d4ull, 0x814d3229a89aa8a8ull, 0x5231f4c496629696ull, + 0x62ef3a9bf9c3f9f9ull, 0xa397f666c533c5c5ull, 0x104ab13525942525ull, 0xabb220f259795959ull, + 0xd015ae54842a8484ull, 0xc5e4a7b772d57272ull, 0xec72ddd539e43939ull, 0x1698615a4c2d4c4cull, + 0x94bc3bca5e655e5eull, 0x9ff085e778fd7878ull, 0xe570d8dd38e03838ull, 0x980586148c0a8c8cull, + 0x17bfb2c6d163d1d1ull, 0xe4570b41a5aea5a5ull, 0xa1d94d43e2afe2e2ull, 0x4ec2f82f61996161ull, + 0x427b45f1b3f6b3b3ull, 0x3442a51521842121ull, 0x0825d6949c4a9c9cull, 0xee3c66f01e781e1eull, + 0x6186522243114343ull, 0xb193fc76c73bc7c7ull, 0x4fe52bb3fcd7fcfcull, 0x2408142004100404ull, + 0xe3a208b251595151ull, 0x252fc7bc995e9999ull, 0x22dac44f6da96d6dull, 0x651a39680d340d0dull, + 0x79e93583facffafaull, 0x69a384b6df5bdfdfull, 0xa9fc9bd77ee57e7eull, 0x1948b43d24902424ull, + 0xfe76d7c53bec3b3bull, 0x9a4b3d31ab96ababull, 0xf081d13ece1fceceull, 0x9922558811441111ull, + 0x8303890c8f068f8full, 0x049c6b4a4e254e4eull, 0x667351d1b7e6b7b7ull, 0xe0cb600beb8bebebull, + 0xc178ccfd3cf03c3cull, 0xfd1fbf7c813e8181ull, 0x4035fed4946a9494ull, 0x1cf30cebf7fbf7f7ull, + 0x186f67a1b9deb9b9ull, 0x8b265f98134c1313ull, 0x51589c7d2cb02c2cull, 0x05bbb8d6d36bd3d3ull, + 0x8cd35c6be7bbe7e7ull, 0x39dccb576ea56e6eull, 0xaa95f36ec437c4c4ull, 0x1b060f18030c0303ull, + 0xdcac138a56455656ull, 0x5e88491a440d4444ull, 0xa0fe9edf7fe17f7full, 0x884f3721a99ea9a9ull, + 0x6754824d2aa82a2aull, 0x0a6b6db1bbd6bbbbull, 0x879fe246c123c1c1ull, 0xf1a602a253515353ull, + 0x72a58baedc57dcdcull, 0x531627580b2c0b0bull, 0x0127d39c9d4e9d9dull, 0x2bd8c1476cad6c6cull, + 0xa462f59531c43131ull, 0xf3e8b98774cd7474ull, 0x15f109e3f6fff6f6ull, 0x4c8c430a46054646ull, + 0xa5452609ac8aacacull, 0xb50f973c891e8989ull, 0xb42844a014501414ull, 0xbadf425be1a3e1e1ull, + 0xa62c4eb016581616ull, 0xf774d2cd3ae83a3aull, 0x06d2d06f69b96969ull, 0x41122d4809240909ull, + 0xd7e0ada770dd7070ull, 0x6f7154d9b6e2b6b6ull, 0x1ebdb7ced067d0d0ull, 0xd6c77e3bed93ededull, + 0xe285db2ecc17ccccull, 0x6884572a42154242ull, 0x2c2dc2b4985a9898ull, 0xed550e49a4aaa4a4ull, + 0x7550885d28a02828ull, 0x86b831da5c6d5c5cull, 0x6bed3f93f8c7f8f8ull, 0xc211a44486228686ull + }, + { + 0x3078c018601818d8ull, 0x46af05238c232326ull, 0x91f97ec63fc6c6b8ull, 0xcd6f13e887e8e8fbull, + 0x13a14c87268787cbull, 0x6d62a9b8dab8b811ull, 0x0205080104010109ull, 0x9e6e424f214f4f0dull, + 0x6ceead36d836369bull, 0x510459a6a2a6a6ffull, 0xb9bdded26fd2d20cull, 0xf706fbf5f3f5f50eull, + 0xf280ef79f9797996ull, 0xdece5f6fa16f6f30ull, 0x3feffc917e91916dull, 0xa407aa52555252f8ull, + 0xc0fd27609d606047ull, 0x657689bccabcbc35ull, 0x2bcdac9b569b9b37ull, 0x018c048e028e8e8aull, + 0x5b1571a3b6a3a3d2ull, 0x183c600c300c0c6cull, 0xf68aff7bf17b7b84ull, 0x6ae1b535d4353580ull, + 0x3a69e81d741d1df5ull, 0xdd4753e0a7e0e0b3ull, 0xb3acf6d77bd7d721ull, 0x99ed5ec22fc2c29cull, + 0x5c966d2eb82e2e43ull, 0x967a624b314b4b29ull, 0xe121a3fedffefe5dull, 0xae168257415757d5ull, + 0x2a41a815541515bdull, 0xeeb69f77c17777e8ull, 0x6eeba537dc373792ull, 0xd7567be5b3e5e59eull, + 0x23d98c9f469f9f13ull, 0xfd17d3f0e7f0f023ull, 0x947f6a4a354a4a20ull, 0xa9959eda4fdada44ull, + 0xb025fa587d5858a2ull, 0x8fca06c903c9c9cfull, 0x528d5529a429297cull, 0x1422500a280a0a5aull, + 0x7f4fe1b1feb1b150ull, 0x5d1a69a0baa0a0c9ull, 0xd6da7f6bb16b6b14ull, 0x17ab5c852e8585d9ull, + 0x677381bdcebdbd3cull, 0xba34d25d695d5d8full, 0x2050801040101090ull, 0xf503f3f4f7f4f407ull, + 0x8bc016cb0bcbcbddull, 0x7cc6ed3ef83e3ed3ull, 0x0a1128051405052dull, 0xcee61f6781676778ull, + 0xd55373e4b7e4e497ull, 0x4ebb25279c272702ull, 0x8258324119414173ull, 0x0b9d2c8b168b8ba7ull, + 0x530151a7a6a7a7f6ull, 0xfa94cf7de97d7db2ull, 0x37fbdc956e959549ull, 0xad9f8ed847d8d856ull, + 0xeb308bfbcbfbfb70ull, 0xc17123ee9feeeecdull, 0xf891c77ced7c7cbbull, 0xcce3176685666671ull, + 0xa78ea6dd53dddd7bull, 0x2e4bb8175c1717afull, 0x8e46024701474745ull, 0x21dc849e429e9e1aull, + 0x89c51eca0fcacad4ull, 0x5a99752db42d2d58ull, 0x637991bfc6bfbf2eull, 0x0e1b38071c07073full, + 0x472301ad8eadadacull, 0xb42fea5a755a5ab0ull, 0x1bb56c83368383efull, 0x66ff8533cc3333b6ull, + 0xc6f23f639163635cull, 0x040a100208020212ull, 0x493839aa92aaaa93ull, 0xe2a8af71d97171deull, + 0x8dcf0ec807c8c8c6ull, 0x327dc819641919d1ull, 0x927072493949493bull, 0xaf9a86d943d9d95full, + 0xf91dc3f2eff2f231ull, 0xdb484be3abe3e3a8ull, 0xb62ae25b715b5bb9ull, 0x0d9234881a8888bcull, + 0x29c8a49a529a9a3eull, 0x4cbe2d269826260bull, 0x64fa8d32c83232bfull, 0x7d4ae9b0fab0b059ull, + 0xcf6a1be983e9e9f2ull, 0x1e33780f3c0f0f77ull, 0xb7a6e6d573d5d533ull, 0x1dba74803a8080f4ull, + 0x617c99bec2bebe27ull, 0x87de26cd13cdcdebull, 0x68e4bd34d0343489ull, 0x90757a483d484832ull, + 0xe324abffdbffff54ull, 0xf48ff77af57a7a8dull, 0x3deaf4907a909064ull, 0xbe3ec25f615f5f9dull, + 0x40a01d208020203dull, 0xd0d56768bd68680full, 0x3472d01a681a1acaull, 0x412c19ae82aeaeb7ull, + 0x755ec9b4eab4b47dull, 0xa8199a544d5454ceull, 0x3be5ec937693937full, 0x44aa0d228822222full, + 0xc8e907648d646463ull, 0xff12dbf1e3f1f12aull, 0xe6a2bf73d17373ccull, 0x245a901248121282ull, + 0x805d3a401d40407aull, 0x1028400820080848ull, 0x9be856c32bc3c395ull, 0xc57b33ec97ececdfull, + 0xab9096db4bdbdb4dull, 0x5f1f61a1bea1a1c0ull, 0x07831c8d0e8d8d91ull, 0x7ac9f53df43d3dc8ull, + 0x33f1cc976697975bull, 0x0000000000000000ull, 0x83d436cf1bcfcff9ull, 0x5687452bac2b2b6eull, + 0xecb39776c57676e1ull, 0x19b06482328282e6ull, 0xb1a9fed67fd6d628ull, 0x3677d81b6c1b1bc3ull, + 0x775bc1b5eeb5b574ull, 0x432911af86afafbeull, 0xd4df776ab56a6a1dull, 0xa00dba505d5050eaull, + 0x8a4c124509454557ull, 0xfb18cbf3ebf3f338ull, 0x60f09d30c03030adull, 0xc3742bef9befefc4ull, + 0x7ec3e53ffc3f3fdaull, 0xaa1c9255495555c7ull, 0x591079a2b2a2a2dbull, 0xc96503ea8feaeae9ull, + 0xcaec0f658965656aull, 0x6968b9bad2baba03ull, 0x5e93652fbc2f2f4aull, 0x9de74ec027c0c08eull, + 0xa181bede5fdede60ull, 0x386ce01c701c1cfcull, 0xe72ebbfdd3fdfd46ull, 0x9a64524d294d4d1full, + 0x39e0e49272929276ull, 0xeabc8f75c97575faull, 0x0c1e300618060636ull, 0x0998248a128a8aaeull, + 0x7940f9b2f2b2b24bull, 0xd15963e6bfe6e685ull, 0x1c36700e380e0e7eull, 0x3e63f81f7c1f1fe7ull, + 0xc4f7376295626255ull, 0xb5a3eed477d4d43aull, 0x4d3229a89aa8a881ull, 0x31f4c49662969652ull, + 0xef3a9bf9c3f9f962ull, 0x97f666c533c5c5a3ull, 0x4ab1352594252510ull, 0xb220f259795959abull, + 0x15ae54842a8484d0ull, 0xe4a7b772d57272c5ull, 0x72ddd539e43939ecull, 0x98615a4c2d4c4c16ull, + 0xbc3bca5e655e5e94ull, 0xf085e778fd78789full, 0x70d8dd38e03838e5ull, 0x0586148c0a8c8c98ull, + 0xbfb2c6d163d1d117ull, 0x570b41a5aea5a5e4ull, 0xd94d43e2afe2e2a1ull, 0xc2f82f619961614eull, + 0x7b45f1b3f6b3b342ull, 0x42a5152184212134ull, 0x25d6949c4a9c9c08ull, 0x3c66f01e781e1eeeull, + 0x8652224311434361ull, 0x93fc76c73bc7c7b1ull, 0xe52bb3fcd7fcfc4full, 0x0814200410040424ull, + 0xa208b251595151e3ull, 0x2fc7bc995e999925ull, 0xdac44f6da96d6d22ull, 0x1a39680d340d0d65ull, + 0xe93583facffafa79ull, 0xa384b6df5bdfdf69ull, 0xfc9bd77ee57e7ea9ull, 0x48b43d2490242419ull, + 0x76d7c53bec3b3bfeull, 0x4b3d31ab96abab9aull, 0x81d13ece1fcecef0ull, 0x2255881144111199ull, + 0x03890c8f068f8f83ull, 0x9c6b4a4e254e4e04ull, 0x7351d1b7e6b7b766ull, 0xcb600beb8bebebe0ull, + 0x78ccfd3cf03c3cc1ull, 0x1fbf7c813e8181fdull, 0x35fed4946a949440ull, 0xf30cebf7fbf7f71cull, + 0x6f67a1b9deb9b918ull, 0x265f98134c13138bull, 0x589c7d2cb02c2c51ull, 0xbbb8d6d36bd3d305ull, + 0xd35c6be7bbe7e78cull, 0xdccb576ea56e6e39ull, 0x95f36ec437c4c4aaull, 0x060f18030c03031bull, + 0xac138a56455656dcull, 0x88491a440d44445eull, 0xfe9edf7fe17f7fa0ull, 0x4f3721a99ea9a988ull, + 0x54824d2aa82a2a67ull, 0x6b6db1bbd6bbbb0aull, 0x9fe246c123c1c187ull, 0xa602a253515353f1ull, + 0xa58baedc57dcdc72ull, 0x1627580b2c0b0b53ull, 0x27d39c9d4e9d9d01ull, 0xd8c1476cad6c6c2bull, + 0x62f59531c43131a4ull, 0xe8b98774cd7474f3ull, 0xf109e3f6fff6f615ull, 0x8c430a460546464cull, + 0x452609ac8aacaca5ull, 0x0f973c891e8989b5ull, 0x2844a014501414b4ull, 0xdf425be1a3e1e1baull, + 0x2c4eb016581616a6ull, 0x74d2cd3ae83a3af7ull, 0xd2d06f69b9696906ull, 0x122d480924090941ull, + 0xe0ada770dd7070d7ull, 0x7154d9b6e2b6b66full, 0xbdb7ced067d0d01eull, 0xc77e3bed93ededd6ull, + 0x85db2ecc17cccce2ull, 0x84572a4215424268ull, 0x2dc2b4985a98982cull, 0x550e49a4aaa4a4edull, + 0x50885d28a0282875ull, 0xb831da5c6d5c5c86ull, 0xed3f93f8c7f8f86bull, 0x11a44486228686c2ull + }, + { + 0x78c018601818d830ull, 0xaf05238c23232646ull, 0xf97ec63fc6c6b891ull, 0x6f13e887e8e8fbcdull, + 0xa14c87268787cb13ull, 0x62a9b8dab8b8116dull, 0x0508010401010902ull, 0x6e424f214f4f0d9eull, + 0xeead36d836369b6cull, 0x0459a6a2a6a6ff51ull, 0xbdded26fd2d20cb9ull, 0x06fbf5f3f5f50ef7ull, + 0x80ef79f9797996f2ull, 0xce5f6fa16f6f30deull, 0xeffc917e91916d3full, 0x07aa52555252f8a4ull, + 0xfd27609d606047c0ull, 0x7689bccabcbc3565ull, 0xcdac9b569b9b372bull, 0x8c048e028e8e8a01ull, + 0x1571a3b6a3a3d25bull, 0x3c600c300c0c6c18ull, 0x8aff7bf17b7b84f6ull, 0xe1b535d43535806aull, + 0x69e81d741d1df53aull, 0x4753e0a7e0e0b3ddull, 0xacf6d77bd7d721b3ull, 0xed5ec22fc2c29c99ull, + 0x966d2eb82e2e435cull, 0x7a624b314b4b2996ull, 0x21a3fedffefe5de1ull, 0x168257415757d5aeull, + 0x41a815541515bd2aull, 0xb69f77c17777e8eeull, 0xeba537dc3737926eull, 0x567be5b3e5e59ed7ull, + 0xd98c9f469f9f1323ull, 0x17d3f0e7f0f023fdull, 0x7f6a4a354a4a2094ull, 0x959eda4fdada44a9ull, + 0x25fa587d5858a2b0ull, 0xca06c903c9c9cf8full, 0x8d5529a429297c52ull, 0x22500a280a0a5a14ull, + 0x4fe1b1feb1b1507full, 0x1a69a0baa0a0c95dull, 0xda7f6bb16b6b14d6ull, 0xab5c852e8585d917ull, + 0x7381bdcebdbd3c67ull, 0x34d25d695d5d8fbaull, 0x5080104010109020ull, 0x03f3f4f7f4f407f5ull, + 0xc016cb0bcbcbdd8bull, 0xc6ed3ef83e3ed37cull, 0x1128051405052d0aull, 0xe61f6781676778ceull, + 0x5373e4b7e4e497d5ull, 0xbb25279c2727024eull, 0x5832411941417382ull, 0x9d2c8b168b8ba70bull, + 0x0151a7a6a7a7f653ull, 0x94cf7de97d7db2faull, 0xfbdc956e95954937ull, 0x9f8ed847d8d856adull, + 0x308bfbcbfbfb70ebull, 0x7123ee9feeeecdc1ull, 0x91c77ced7c7cbbf8ull, 0xe3176685666671ccull, + 0x8ea6dd53dddd7ba7ull, 0x4bb8175c1717af2eull, 0x460247014747458eull, 0xdc849e429e9e1a21ull, + 0xc51eca0fcacad489ull, 0x99752db42d2d585aull, 0x7991bfc6bfbf2e63ull, 0x1b38071c07073f0eull, + 0x2301ad8eadadac47ull, 0x2fea5a755a5ab0b4ull, 0xb56c83368383ef1bull, 0xff8533cc3333b666ull, + 0xf23f639163635cc6ull, 0x0a10020802021204ull, 0x3839aa92aaaa9349ull, 0xa8af71d97171dee2ull, + 0xcf0ec807c8c8c68dull, 0x7dc819641919d132ull, 0x7072493949493b92ull, 0x9a86d943d9d95fafull, + 0x1dc3f2eff2f231f9ull, 0x484be3abe3e3a8dbull, 0x2ae25b715b5bb9b6ull, 0x9234881a8888bc0dull, + 0xc8a49a529a9a3e29ull, 0xbe2d269826260b4cull, 0xfa8d32c83232bf64ull, 0x4ae9b0fab0b0597dull, + 0x6a1be983e9e9f2cfull, 0x33780f3c0f0f771eull, 0xa6e6d573d5d533b7ull, 0xba74803a8080f41dull, + 0x7c99bec2bebe2761ull, 0xde26cd13cdcdeb87ull, 0xe4bd34d034348968ull, 0x757a483d48483290ull, + 0x24abffdbffff54e3ull, 0x8ff77af57a7a8df4ull, 0xeaf4907a9090643dull, 0x3ec25f615f5f9dbeull, + 0xa01d208020203d40ull, 0xd56768bd68680fd0ull, 0x72d01a681a1aca34ull, 0x2c19ae82aeaeb741ull, + 0x5ec9b4eab4b47d75ull, 0x199a544d5454cea8ull, 0xe5ec937693937f3bull, 0xaa0d228822222f44ull, + 0xe907648d646463c8ull, 0x12dbf1e3f1f12affull, 0xa2bf73d17373cce6ull, 0x5a90124812128224ull, + 0x5d3a401d40407a80ull, 0x2840082008084810ull, 0xe856c32bc3c3959bull, 0x7b33ec97ececdfc5ull, + 0x9096db4bdbdb4dabull, 0x1f61a1bea1a1c05full, 0x831c8d0e8d8d9107ull, 0xc9f53df43d3dc87aull, + 0xf1cc976697975b33ull, 0x0000000000000000ull, 0xd436cf1bcfcff983ull, 0x87452bac2b2b6e56ull, + 0xb39776c57676e1ecull, 0xb06482328282e619ull, 0xa9fed67fd6d628b1ull, 0x77d81b6c1b1bc336ull, + 0x5bc1b5eeb5b57477ull, 0x2911af86afafbe43ull, 0xdf776ab56a6a1dd4ull, 0x0dba505d5050eaa0ull, + 0x4c1245094545578aull, 0x18cbf3ebf3f338fbull, 0xf09d30c03030ad60ull, 0x742bef9befefc4c3ull, + 0xc3e53ffc3f3fda7eull, 0x1c9255495555c7aaull, 0x1079a2b2a2a2db59ull, 0x6503ea8feaeae9c9ull, + 0xec0f658965656acaull, 0x68b9bad2baba0369ull, 0x93652fbc2f2f4a5eull, 0xe74ec027c0c08e9dull, + 0x81bede5fdede60a1ull, 0x6ce01c701c1cfc38ull, 0x2ebbfdd3fdfd46e7ull, 0x64524d294d4d1f9aull, + 0xe0e4927292927639ull, 0xbc8f75c97575faeaull, 0x1e3006180606360cull, 0x98248a128a8aae09ull, + 0x40f9b2f2b2b24b79ull, 0x5963e6bfe6e685d1ull, 0x36700e380e0e7e1cull, 0x63f81f7c1f1fe73eull, + 0xf7376295626255c4ull, 0xa3eed477d4d43ab5ull, 0x3229a89aa8a8814dull, 0xf4c4966296965231ull, + 0x3a9bf9c3f9f962efull, 0xf666c533c5c5a397ull, 0xb13525942525104aull, 0x20f259795959abb2ull, + 0xae54842a8484d015ull, 0xa7b772d57272c5e4ull, 0xddd539e43939ec72ull, 0x615a4c2d4c4c1698ull, + 0x3bca5e655e5e94bcull, 0x85e778fd78789ff0ull, 0xd8dd38e03838e570ull, 0x86148c0a8c8c9805ull, + 0xb2c6d163d1d117bfull, 0x0b41a5aea5a5e457ull, 0x4d43e2afe2e2a1d9ull, 0xf82f619961614ec2ull, + 0x45f1b3f6b3b3427bull, 0xa515218421213442ull, 0xd6949c4a9c9c0825ull, 0x66f01e781e1eee3cull, + 0x5222431143436186ull, 0xfc76c73bc7c7b193ull, 0x2bb3fcd7fcfc4fe5ull, 0x1420041004042408ull, + 0x08b251595151e3a2ull, 0xc7bc995e9999252full, 0xc44f6da96d6d22daull, 0x39680d340d0d651aull, + 0x3583facffafa79e9ull, 0x84b6df5bdfdf69a3ull, 0x9bd77ee57e7ea9fcull, 0xb43d249024241948ull, + 0xd7c53bec3b3bfe76ull, 0x3d31ab96abab9a4bull, 0xd13ece1fcecef081ull, 0x5588114411119922ull, + 0x890c8f068f8f8303ull, 0x6b4a4e254e4e049cull, 0x51d1b7e6b7b76673ull, 0x600beb8bebebe0cbull, + 0xccfd3cf03c3cc178ull, 0xbf7c813e8181fd1full, 0xfed4946a94944035ull, 0x0cebf7fbf7f71cf3ull, + 0x67a1b9deb9b9186full, 0x5f98134c13138b26ull, 0x9c7d2cb02c2c5158ull, 0xb8d6d36bd3d305bbull, + 0x5c6be7bbe7e78cd3ull, 0xcb576ea56e6e39dcull, 0xf36ec437c4c4aa95ull, 0x0f18030c03031b06ull, + 0x138a56455656dcacull, 0x491a440d44445e88ull, 0x9edf7fe17f7fa0feull, 0x3721a99ea9a9884full, + 0x824d2aa82a2a6754ull, 0x6db1bbd6bbbb0a6bull, 0xe246c123c1c1879full, 0x02a253515353f1a6ull, + 0x8baedc57dcdc72a5ull, 0x27580b2c0b0b5316ull, 0xd39c9d4e9d9d0127ull, 0xc1476cad6c6c2bd8ull, + 0xf59531c43131a462ull, 0xb98774cd7474f3e8ull, 0x09e3f6fff6f615f1ull, 0x430a460546464c8cull, + 0x2609ac8aacaca545ull, 0x973c891e8989b50full, 0x44a014501414b428ull, 0x425be1a3e1e1badfull, + 0x4eb016581616a62cull, 0xd2cd3ae83a3af774ull, 0xd06f69b9696906d2ull, 0x2d48092409094112ull, + 0xada770dd7070d7e0ull, 0x54d9b6e2b6b66f71ull, 0xb7ced067d0d01ebdull, 0x7e3bed93ededd6c7ull, + 0xdb2ecc17cccce285ull, 0x572a421542426884ull, 0xc2b4985a98982c2dull, 0x0e49a4aaa4a4ed55ull, + 0x885d28a028287550ull, 0x31da5c6d5c5c86b8ull, 0x3f93f8c7f8f86bedull, 0xa44486228686c211ull + }, + { + 0xc018601818d83078ull, 0x05238c23232646afull, 0x7ec63fc6c6b891f9ull, 0x13e887e8e8fbcd6full, + 0x4c87268787cb13a1ull, 0xa9b8dab8b8116d62ull, 0x0801040101090205ull, 0x424f214f4f0d9e6eull, + 0xad36d836369b6ceeull, 0x59a6a2a6a6ff5104ull, 0xded26fd2d20cb9bdull, 0xfbf5f3f5f50ef706ull, + 0xef79f9797996f280ull, 0x5f6fa16f6f30deceull, 0xfc917e91916d3fefull, 0xaa52555252f8a407ull, + 0x27609d606047c0fdull, 0x89bccabcbc356576ull, 0xac9b569b9b372bcdull, 0x048e028e8e8a018cull, + 0x71a3b6a3a3d25b15ull, 0x600c300c0c6c183cull, 0xff7bf17b7b84f68aull, 0xb535d43535806ae1ull, + 0xe81d741d1df53a69ull, 0x53e0a7e0e0b3dd47ull, 0xf6d77bd7d721b3acull, 0x5ec22fc2c29c99edull, + 0x6d2eb82e2e435c96ull, 0x624b314b4b29967aull, 0xa3fedffefe5de121ull, 0x8257415757d5ae16ull, + 0xa815541515bd2a41ull, 0x9f77c17777e8eeb6ull, 0xa537dc3737926eebull, 0x7be5b3e5e59ed756ull, + 0x8c9f469f9f1323d9ull, 0xd3f0e7f0f023fd17ull, 0x6a4a354a4a20947full, 0x9eda4fdada44a995ull, + 0xfa587d5858a2b025ull, 0x06c903c9c9cf8fcaull, 0x5529a429297c528dull, 0x500a280a0a5a1422ull, + 0xe1b1feb1b1507f4full, 0x69a0baa0a0c95d1aull, 0x7f6bb16b6b14d6daull, 0x5c852e8585d917abull, + 0x81bdcebdbd3c6773ull, 0xd25d695d5d8fba34ull, 0x8010401010902050ull, 0xf3f4f7f4f407f503ull, + 0x16cb0bcbcbdd8bc0ull, 0xed3ef83e3ed37cc6ull, 0x28051405052d0a11ull, 0x1f6781676778cee6ull, + 0x73e4b7e4e497d553ull, 0x25279c2727024ebbull, 0x3241194141738258ull, 0x2c8b168b8ba70b9dull, + 0x51a7a6a7a7f65301ull, 0xcf7de97d7db2fa94ull, 0xdc956e95954937fbull, 0x8ed847d8d856ad9full, + 0x8bfbcbfbfb70eb30ull, 0x23ee9feeeecdc171ull, 0xc77ced7c7cbbf891ull, 0x176685666671cce3ull, + 0xa6dd53dddd7ba78eull, 0xb8175c1717af2e4bull, 0x0247014747458e46ull, 0x849e429e9e1a21dcull, + 0x1eca0fcacad489c5ull, 0x752db42d2d585a99ull, 0x91bfc6bfbf2e6379ull, 0x38071c07073f0e1bull, + 0x01ad8eadadac4723ull, 0xea5a755a5ab0b42full, 0x6c83368383ef1bb5ull, 0x8533cc3333b666ffull, + 0x3f639163635cc6f2ull, 0x100208020212040aull, 0x39aa92aaaa934938ull, 0xaf71d97171dee2a8ull, + 0x0ec807c8c8c68dcfull, 0xc819641919d1327dull, 0x72493949493b9270ull, 0x86d943d9d95faf9aull, + 0xc3f2eff2f231f91dull, 0x4be3abe3e3a8db48ull, 0xe25b715b5bb9b62aull, 0x34881a8888bc0d92ull, + 0xa49a529a9a3e29c8ull, 0x2d269826260b4cbeull, 0x8d32c83232bf64faull, 0xe9b0fab0b0597d4aull, + 0x1be983e9e9f2cf6aull, 0x780f3c0f0f771e33ull, 0xe6d573d5d533b7a6ull, 0x74803a8080f41dbaull, + 0x99bec2bebe27617cull, 0x26cd13cdcdeb87deull, 0xbd34d034348968e4ull, 0x7a483d4848329075ull, + 0xabffdbffff54e324ull, 0xf77af57a7a8df48full, 0xf4907a9090643deaull, 0xc25f615f5f9dbe3eull, + 0x1d208020203d40a0ull, 0x6768bd68680fd0d5ull, 0xd01a681a1aca3472ull, 0x19ae82aeaeb7412cull, + 0xc9b4eab4b47d755eull, 0x9a544d5454cea819ull, 0xec937693937f3be5ull, 0x0d228822222f44aaull, + 0x07648d646463c8e9ull, 0xdbf1e3f1f12aff12ull, 0xbf73d17373cce6a2ull, 0x901248121282245aull, + 0x3a401d40407a805dull, 0x4008200808481028ull, 0x56c32bc3c3959be8ull, 0x33ec97ececdfc57bull, + 0x96db4bdbdb4dab90ull, 0x61a1bea1a1c05f1full, 0x1c8d0e8d8d910783ull, 0xf53df43d3dc87ac9ull, + 0xcc976697975b33f1ull, 0x0000000000000000ull, 0x36cf1bcfcff983d4ull, 0x452bac2b2b6e5687ull, + 0x9776c57676e1ecb3ull, 0x6482328282e619b0ull, 0xfed67fd6d628b1a9ull, 0xd81b6c1b1bc33677ull, + 0xc1b5eeb5b574775bull, 0x11af86afafbe4329ull, 0x776ab56a6a1dd4dfull, 0xba505d5050eaa00dull, + 0x1245094545578a4cull, 0xcbf3ebf3f338fb18ull, 0x9d30c03030ad60f0ull, 0x2bef9befefc4c374ull, + 0xe53ffc3f3fda7ec3ull, 0x9255495555c7aa1cull, 0x79a2b2a2a2db5910ull, 0x03ea8feaeae9c965ull, + 0x0f658965656acaecull, 0xb9bad2baba036968ull, 0x652fbc2f2f4a5e93ull, 0x4ec027c0c08e9de7ull, + 0xbede5fdede60a181ull, 0xe01c701c1cfc386cull, 0xbbfdd3fdfd46e72eull, 0x524d294d4d1f9a64ull, + 0xe4927292927639e0ull, 0x8f75c97575faeabcull, 0x3006180606360c1eull, 0x248a128a8aae0998ull, + 0xf9b2f2b2b24b7940ull, 0x63e6bfe6e685d159ull, 0x700e380e0e7e1c36ull, 0xf81f7c1f1fe73e63ull, + 0x376295626255c4f7ull, 0xeed477d4d43ab5a3ull, 0x29a89aa8a8814d32ull, 0xc4966296965231f4ull, + 0x9bf9c3f9f962ef3aull, 0x66c533c5c5a397f6ull, 0x3525942525104ab1ull, 0xf259795959abb220ull, + 0x54842a8484d015aeull, 0xb772d57272c5e4a7ull, 0xd539e43939ec72ddull, 0x5a4c2d4c4c169861ull, + 0xca5e655e5e94bc3bull, 0xe778fd78789ff085ull, 0xdd38e03838e570d8ull, 0x148c0a8c8c980586ull, + 0xc6d163d1d117bfb2ull, 0x41a5aea5a5e4570bull, 0x43e2afe2e2a1d94dull, 0x2f619961614ec2f8ull, + 0xf1b3f6b3b3427b45ull, 0x15218421213442a5ull, 0x949c4a9c9c0825d6ull, 0xf01e781e1eee3c66ull, + 0x2243114343618652ull, 0x76c73bc7c7b193fcull, 0xb3fcd7fcfc4fe52bull, 0x2004100404240814ull, + 0xb251595151e3a208ull, 0xbc995e9999252fc7ull, 0x4f6da96d6d22dac4ull, 0x680d340d0d651a39ull, + 0x83facffafa79e935ull, 0xb6df5bdfdf69a384ull, 0xd77ee57e7ea9fc9bull, 0x3d249024241948b4ull, + 0xc53bec3b3bfe76d7ull, 0x31ab96abab9a4b3dull, 0x3ece1fcecef081d1ull, 0x8811441111992255ull, + 0x0c8f068f8f830389ull, 0x4a4e254e4e049c6bull, 0xd1b7e6b7b7667351ull, 0x0beb8bebebe0cb60ull, + 0xfd3cf03c3cc178ccull, 0x7c813e8181fd1fbfull, 0xd4946a94944035feull, 0xebf7fbf7f71cf30cull, + 0xa1b9deb9b9186f67ull, 0x98134c13138b265full, 0x7d2cb02c2c51589cull, 0xd6d36bd3d305bbb8ull, + 0x6be7bbe7e78cd35cull, 0x576ea56e6e39dccbull, 0x6ec437c4c4aa95f3ull, 0x18030c03031b060full, + 0x8a56455656dcac13ull, 0x1a440d44445e8849ull, 0xdf7fe17f7fa0fe9eull, 0x21a99ea9a9884f37ull, + 0x4d2aa82a2a675482ull, 0xb1bbd6bbbb0a6b6dull, 0x46c123c1c1879fe2ull, 0xa253515353f1a602ull, + 0xaedc57dcdc72a58bull, 0x580b2c0b0b531627ull, 0x9c9d4e9d9d0127d3ull, 0x476cad6c6c2bd8c1ull, + 0x9531c43131a462f5ull, 0x8774cd7474f3e8b9ull, 0xe3f6fff6f615f109ull, 0x0a460546464c8c43ull, + 0x09ac8aacaca54526ull, 0x3c891e8989b50f97ull, 0xa014501414b42844ull, 0x5be1a3e1e1badf42ull, + 0xb016581616a62c4eull, 0xcd3ae83a3af774d2ull, 0x6f69b9696906d2d0ull, 0x480924090941122dull, + 0xa770dd7070d7e0adull, 0xd9b6e2b6b66f7154ull, 0xced067d0d01ebdb7ull, 0x3bed93ededd6c77eull, + 0x2ecc17cccce285dbull, 0x2a42154242688457ull, 0xb4985a98982c2dc2ull, 0x49a4aaa4a4ed550eull, + 0x5d28a02828755088ull, 0xda5c6d5c5c86b831ull, 0x93f8c7f8f86bed3full, 0x4486228686c211a4ull + }, + { + 0x18601818d83078c0ull, 0x238c23232646af05ull, 0xc63fc6c6b891f97eull, 0xe887e8e8fbcd6f13ull, + 0x87268787cb13a14cull, 0xb8dab8b8116d62a9ull, 0x0104010109020508ull, 0x4f214f4f0d9e6e42ull, + 0x36d836369b6ceeadull, 0xa6a2a6a6ff510459ull, 0xd26fd2d20cb9bddeull, 0xf5f3f5f50ef706fbull, + 0x79f9797996f280efull, 0x6fa16f6f30dece5full, 0x917e91916d3feffcull, 0x52555252f8a407aaull, + 0x609d606047c0fd27ull, 0xbccabcbc35657689ull, 0x9b569b9b372bcdacull, 0x8e028e8e8a018c04ull, + 0xa3b6a3a3d25b1571ull, 0x0c300c0c6c183c60ull, 0x7bf17b7b84f68affull, 0x35d43535806ae1b5ull, + 0x1d741d1df53a69e8ull, 0xe0a7e0e0b3dd4753ull, 0xd77bd7d721b3acf6ull, 0xc22fc2c29c99ed5eull, + 0x2eb82e2e435c966dull, 0x4b314b4b29967a62ull, 0xfedffefe5de121a3ull, 0x57415757d5ae1682ull, + 0x15541515bd2a41a8ull, 0x77c17777e8eeb69full, 0x37dc3737926eeba5ull, 0xe5b3e5e59ed7567bull, + 0x9f469f9f1323d98cull, 0xf0e7f0f023fd17d3ull, 0x4a354a4a20947f6aull, 0xda4fdada44a9959eull, + 0x587d5858a2b025faull, 0xc903c9c9cf8fca06ull, 0x29a429297c528d55ull, 0x0a280a0a5a142250ull, + 0xb1feb1b1507f4fe1ull, 0xa0baa0a0c95d1a69ull, 0x6bb16b6b14d6da7full, 0x852e8585d917ab5cull, + 0xbdcebdbd3c677381ull, 0x5d695d5d8fba34d2ull, 0x1040101090205080ull, 0xf4f7f4f407f503f3ull, + 0xcb0bcbcbdd8bc016ull, 0x3ef83e3ed37cc6edull, 0x051405052d0a1128ull, 0x6781676778cee61full, + 0xe4b7e4e497d55373ull, 0x279c2727024ebb25ull, 0x4119414173825832ull, 0x8b168b8ba70b9d2cull, + 0xa7a6a7a7f6530151ull, 0x7de97d7db2fa94cfull, 0x956e95954937fbdcull, 0xd847d8d856ad9f8eull, + 0xfbcbfbfb70eb308bull, 0xee9feeeecdc17123ull, 0x7ced7c7cbbf891c7ull, 0x6685666671cce317ull, + 0xdd53dddd7ba78ea6ull, 0x175c1717af2e4bb8ull, 0x47014747458e4602ull, 0x9e429e9e1a21dc84ull, + 0xca0fcacad489c51eull, 0x2db42d2d585a9975ull, 0xbfc6bfbf2e637991ull, 0x071c07073f0e1b38ull, + 0xad8eadadac472301ull, 0x5a755a5ab0b42feaull, 0x83368383ef1bb56cull, 0x33cc3333b666ff85ull, + 0x639163635cc6f23full, 0x0208020212040a10ull, 0xaa92aaaa93493839ull, 0x71d97171dee2a8afull, + 0xc807c8c8c68dcf0eull, 0x19641919d1327dc8ull, 0x493949493b927072ull, 0xd943d9d95faf9a86ull, + 0xf2eff2f231f91dc3ull, 0xe3abe3e3a8db484bull, 0x5b715b5bb9b62ae2ull, 0x881a8888bc0d9234ull, + 0x9a529a9a3e29c8a4ull, 0x269826260b4cbe2dull, 0x32c83232bf64fa8dull, 0xb0fab0b0597d4ae9ull, + 0xe983e9e9f2cf6a1bull, 0x0f3c0f0f771e3378ull, 0xd573d5d533b7a6e6ull, 0x803a8080f41dba74ull, + 0xbec2bebe27617c99ull, 0xcd13cdcdeb87de26ull, 0x34d034348968e4bdull, 0x483d48483290757aull, + 0xffdbffff54e324abull, 0x7af57a7a8df48ff7ull, 0x907a9090643deaf4ull, 0x5f615f5f9dbe3ec2ull, + 0x208020203d40a01dull, 0x68bd68680fd0d567ull, 0x1a681a1aca3472d0ull, 0xae82aeaeb7412c19ull, + 0xb4eab4b47d755ec9ull, 0x544d5454cea8199aull, 0x937693937f3be5ecull, 0x228822222f44aa0dull, + 0x648d646463c8e907ull, 0xf1e3f1f12aff12dbull, 0x73d17373cce6a2bfull, 0x1248121282245a90ull, + 0x401d40407a805d3aull, 0x0820080848102840ull, 0xc32bc3c3959be856ull, 0xec97ececdfc57b33ull, + 0xdb4bdbdb4dab9096ull, 0xa1bea1a1c05f1f61ull, 0x8d0e8d8d9107831cull, 0x3df43d3dc87ac9f5ull, + 0x976697975b33f1ccull, 0x0000000000000000ull, 0xcf1bcfcff983d436ull, 0x2bac2b2b6e568745ull, + 0x76c57676e1ecb397ull, 0x82328282e619b064ull, 0xd67fd6d628b1a9feull, 0x1b6c1b1bc33677d8ull, + 0xb5eeb5b574775bc1ull, 0xaf86afafbe432911ull, 0x6ab56a6a1dd4df77ull, 0x505d5050eaa00dbaull, + 0x45094545578a4c12ull, 0xf3ebf3f338fb18cbull, 0x30c03030ad60f09dull, 0xef9befefc4c3742bull, + 0x3ffc3f3fda7ec3e5ull, 0x55495555c7aa1c92ull, 0xa2b2a2a2db591079ull, 0xea8feaeae9c96503ull, + 0x658965656acaec0full, 0xbad2baba036968b9ull, 0x2fbc2f2f4a5e9365ull, 0xc027c0c08e9de74eull, + 0xde5fdede60a181beull, 0x1c701c1cfc386ce0ull, 0xfdd3fdfd46e72ebbull, 0x4d294d4d1f9a6452ull, + 0x927292927639e0e4ull, 0x75c97575faeabc8full, 0x06180606360c1e30ull, 0x8a128a8aae099824ull, + 0xb2f2b2b24b7940f9ull, 0xe6bfe6e685d15963ull, 0x0e380e0e7e1c3670ull, 0x1f7c1f1fe73e63f8ull, + 0x6295626255c4f737ull, 0xd477d4d43ab5a3eeull, 0xa89aa8a8814d3229ull, 0x966296965231f4c4ull, + 0xf9c3f9f962ef3a9bull, 0xc533c5c5a397f666ull, 0x25942525104ab135ull, 0x59795959abb220f2ull, + 0x842a8484d015ae54ull, 0x72d57272c5e4a7b7ull, 0x39e43939ec72ddd5ull, 0x4c2d4c4c1698615aull, + 0x5e655e5e94bc3bcaull, 0x78fd78789ff085e7ull, 0x38e03838e570d8ddull, 0x8c0a8c8c98058614ull, + 0xd163d1d117bfb2c6ull, 0xa5aea5a5e4570b41ull, 0xe2afe2e2a1d94d43ull, 0x619961614ec2f82full, + 0xb3f6b3b3427b45f1ull, 0x218421213442a515ull, 0x9c4a9c9c0825d694ull, 0x1e781e1eee3c66f0ull, + 0x4311434361865222ull, 0xc73bc7c7b193fc76ull, 0xfcd7fcfc4fe52bb3ull, 0x0410040424081420ull, + 0x51595151e3a208b2ull, 0x995e9999252fc7bcull, 0x6da96d6d22dac44full, 0x0d340d0d651a3968ull, + 0xfacffafa79e93583ull, 0xdf5bdfdf69a384b6ull, 0x7ee57e7ea9fc9bd7ull, 0x249024241948b43dull, + 0x3bec3b3bfe76d7c5ull, 0xab96abab9a4b3d31ull, 0xce1fcecef081d13eull, 0x1144111199225588ull, + 0x8f068f8f8303890cull, 0x4e254e4e049c6b4aull, 0xb7e6b7b7667351d1ull, 0xeb8bebebe0cb600bull, + 0x3cf03c3cc178ccfdull, 0x813e8181fd1fbf7cull, 0x946a94944035fed4ull, 0xf7fbf7f71cf30cebull, + 0xb9deb9b9186f67a1ull, 0x134c13138b265f98ull, 0x2cb02c2c51589c7dull, 0xd36bd3d305bbb8d6ull, + 0xe7bbe7e78cd35c6bull, 0x6ea56e6e39dccb57ull, 0xc437c4c4aa95f36eull, 0x030c03031b060f18ull, + 0x56455656dcac138aull, 0x440d44445e88491aull, 0x7fe17f7fa0fe9edfull, 0xa99ea9a9884f3721ull, + 0x2aa82a2a6754824dull, 0xbbd6bbbb0a6b6db1ull, 0xc123c1c1879fe246ull, 0x53515353f1a602a2ull, + 0xdc57dcdc72a58baeull, 0x0b2c0b0b53162758ull, 0x9d4e9d9d0127d39cull, 0x6cad6c6c2bd8c147ull, + 0x31c43131a462f595ull, 0x74cd7474f3e8b987ull, 0xf6fff6f615f109e3ull, 0x460546464c8c430aull, + 0xac8aacaca5452609ull, 0x891e8989b50f973cull, 0x14501414b42844a0ull, 0xe1a3e1e1badf425bull, + 0x16581616a62c4eb0ull, 0x3ae83a3af774d2cdull, 0x69b9696906d2d06full, 0x0924090941122d48ull, + 0x70dd7070d7e0ada7ull, 0xb6e2b6b66f7154d9ull, 0xd067d0d01ebdb7ceull, 0xed93ededd6c77e3bull, + 0xcc17cccce285db2eull, 0x421542426884572aull, 0x985a98982c2dc2b4ull, 0xa4aaa4a4ed550e49ull, + 0x28a028287550885dull, 0x5c6d5c5c86b831daull, 0xf8c7f8f86bed3f93ull, 0x86228686c211a444ull + }, + { + 0x601818d83078c018ull, 0x8c23232646af0523ull, 0x3fc6c6b891f97ec6ull, 0x87e8e8fbcd6f13e8ull, + 0x268787cb13a14c87ull, 0xdab8b8116d62a9b8ull, 0x0401010902050801ull, 0x214f4f0d9e6e424full, + 0xd836369b6ceead36ull, 0xa2a6a6ff510459a6ull, 0x6fd2d20cb9bdded2ull, 0xf3f5f50ef706fbf5ull, + 0xf9797996f280ef79ull, 0xa16f6f30dece5f6full, 0x7e91916d3feffc91ull, 0x555252f8a407aa52ull, + 0x9d606047c0fd2760ull, 0xcabcbc35657689bcull, 0x569b9b372bcdac9bull, 0x028e8e8a018c048eull, + 0xb6a3a3d25b1571a3ull, 0x300c0c6c183c600cull, 0xf17b7b84f68aff7bull, 0xd43535806ae1b535ull, + 0x741d1df53a69e81dull, 0xa7e0e0b3dd4753e0ull, 0x7bd7d721b3acf6d7ull, 0x2fc2c29c99ed5ec2ull, + 0xb82e2e435c966d2eull, 0x314b4b29967a624bull, 0xdffefe5de121a3feull, 0x415757d5ae168257ull, + 0x541515bd2a41a815ull, 0xc17777e8eeb69f77ull, 0xdc3737926eeba537ull, 0xb3e5e59ed7567be5ull, + 0x469f9f1323d98c9full, 0xe7f0f023fd17d3f0ull, 0x354a4a20947f6a4aull, 0x4fdada44a9959edaull, + 0x7d5858a2b025fa58ull, 0x03c9c9cf8fca06c9ull, 0xa429297c528d5529ull, 0x280a0a5a1422500aull, + 0xfeb1b1507f4fe1b1ull, 0xbaa0a0c95d1a69a0ull, 0xb16b6b14d6da7f6bull, 0x2e8585d917ab5c85ull, + 0xcebdbd3c677381bdull, 0x695d5d8fba34d25dull, 0x4010109020508010ull, 0xf7f4f407f503f3f4ull, + 0x0bcbcbdd8bc016cbull, 0xf83e3ed37cc6ed3eull, 0x1405052d0a112805ull, 0x81676778cee61f67ull, + 0xb7e4e497d55373e4ull, 0x9c2727024ebb2527ull, 0x1941417382583241ull, 0x168b8ba70b9d2c8bull, + 0xa6a7a7f6530151a7ull, 0xe97d7db2fa94cf7dull, 0x6e95954937fbdc95ull, 0x47d8d856ad9f8ed8ull, + 0xcbfbfb70eb308bfbull, 0x9feeeecdc17123eeull, 0xed7c7cbbf891c77cull, 0x85666671cce31766ull, + 0x53dddd7ba78ea6ddull, 0x5c1717af2e4bb817ull, 0x014747458e460247ull, 0x429e9e1a21dc849eull, + 0x0fcacad489c51ecaull, 0xb42d2d585a99752dull, 0xc6bfbf2e637991bfull, 0x1c07073f0e1b3807ull, + 0x8eadadac472301adull, 0x755a5ab0b42fea5aull, 0x368383ef1bb56c83ull, 0xcc3333b666ff8533ull, + 0x9163635cc6f23f63ull, 0x08020212040a1002ull, 0x92aaaa93493839aaull, 0xd97171dee2a8af71ull, + 0x07c8c8c68dcf0ec8ull, 0x641919d1327dc819ull, 0x3949493b92707249ull, 0x43d9d95faf9a86d9ull, + 0xeff2f231f91dc3f2ull, 0xabe3e3a8db484be3ull, 0x715b5bb9b62ae25bull, 0x1a8888bc0d923488ull, + 0x529a9a3e29c8a49aull, 0x9826260b4cbe2d26ull, 0xc83232bf64fa8d32ull, 0xfab0b0597d4ae9b0ull, + 0x83e9e9f2cf6a1be9ull, 0x3c0f0f771e33780full, 0x73d5d533b7a6e6d5ull, 0x3a8080f41dba7480ull, + 0xc2bebe27617c99beull, 0x13cdcdeb87de26cdull, 0xd034348968e4bd34ull, 0x3d48483290757a48ull, + 0xdbffff54e324abffull, 0xf57a7a8df48ff77aull, 0x7a9090643deaf490ull, 0x615f5f9dbe3ec25full, + 0x8020203d40a01d20ull, 0xbd68680fd0d56768ull, 0x681a1aca3472d01aull, 0x82aeaeb7412c19aeull, + 0xeab4b47d755ec9b4ull, 0x4d5454cea8199a54ull, 0x7693937f3be5ec93ull, 0x8822222f44aa0d22ull, + 0x8d646463c8e90764ull, 0xe3f1f12aff12dbf1ull, 0xd17373cce6a2bf73ull, 0x48121282245a9012ull, + 0x1d40407a805d3a40ull, 0x2008084810284008ull, 0x2bc3c3959be856c3ull, 0x97ececdfc57b33ecull, + 0x4bdbdb4dab9096dbull, 0xbea1a1c05f1f61a1ull, 0x0e8d8d9107831c8dull, 0xf43d3dc87ac9f53dull, + 0x6697975b33f1cc97ull, 0x0000000000000000ull, 0x1bcfcff983d436cfull, 0xac2b2b6e5687452bull, + 0xc57676e1ecb39776ull, 0x328282e619b06482ull, 0x7fd6d628b1a9fed6ull, 0x6c1b1bc33677d81bull, + 0xeeb5b574775bc1b5ull, 0x86afafbe432911afull, 0xb56a6a1dd4df776aull, 0x5d5050eaa00dba50ull, + 0x094545578a4c1245ull, 0xebf3f338fb18cbf3ull, 0xc03030ad60f09d30ull, 0x9befefc4c3742befull, + 0xfc3f3fda7ec3e53full, 0x495555c7aa1c9255ull, 0xb2a2a2db591079a2ull, 0x8feaeae9c96503eaull, + 0x8965656acaec0f65ull, 0xd2baba036968b9baull, 0xbc2f2f4a5e93652full, 0x27c0c08e9de74ec0ull, + 0x5fdede60a181bedeull, 0x701c1cfc386ce01cull, 0xd3fdfd46e72ebbfdull, 0x294d4d1f9a64524dull, + 0x7292927639e0e492ull, 0xc97575faeabc8f75ull, 0x180606360c1e3006ull, 0x128a8aae0998248aull, + 0xf2b2b24b7940f9b2ull, 0xbfe6e685d15963e6ull, 0x380e0e7e1c36700eull, 0x7c1f1fe73e63f81full, + 0x95626255c4f73762ull, 0x77d4d43ab5a3eed4ull, 0x9aa8a8814d3229a8ull, 0x6296965231f4c496ull, + 0xc3f9f962ef3a9bf9ull, 0x33c5c5a397f666c5ull, 0x942525104ab13525ull, 0x795959abb220f259ull, + 0x2a8484d015ae5484ull, 0xd57272c5e4a7b772ull, 0xe43939ec72ddd539ull, 0x2d4c4c1698615a4cull, + 0x655e5e94bc3bca5eull, 0xfd78789ff085e778ull, 0xe03838e570d8dd38ull, 0x0a8c8c980586148cull, + 0x63d1d117bfb2c6d1ull, 0xaea5a5e4570b41a5ull, 0xafe2e2a1d94d43e2ull, 0x9961614ec2f82f61ull, + 0xf6b3b3427b45f1b3ull, 0x8421213442a51521ull, 0x4a9c9c0825d6949cull, 0x781e1eee3c66f01eull, + 0x1143436186522243ull, 0x3bc7c7b193fc76c7ull, 0xd7fcfc4fe52bb3fcull, 0x1004042408142004ull, + 0x595151e3a208b251ull, 0x5e9999252fc7bc99ull, 0xa96d6d22dac44f6dull, 0x340d0d651a39680dull, + 0xcffafa79e93583faull, 0x5bdfdf69a384b6dfull, 0xe57e7ea9fc9bd77eull, 0x9024241948b43d24ull, + 0xec3b3bfe76d7c53bull, 0x96abab9a4b3d31abull, 0x1fcecef081d13eceull, 0x4411119922558811ull, + 0x068f8f8303890c8full, 0x254e4e049c6b4a4eull, 0xe6b7b7667351d1b7ull, 0x8bebebe0cb600bebull, + 0xf03c3cc178ccfd3cull, 0x3e8181fd1fbf7c81ull, 0x6a94944035fed494ull, 0xfbf7f71cf30cebf7ull, + 0xdeb9b9186f67a1b9ull, 0x4c13138b265f9813ull, 0xb02c2c51589c7d2cull, 0x6bd3d305bbb8d6d3ull, + 0xbbe7e78cd35c6be7ull, 0xa56e6e39dccb576eull, 0x37c4c4aa95f36ec4ull, 0x0c03031b060f1803ull, + 0x455656dcac138a56ull, 0x0d44445e88491a44ull, 0xe17f7fa0fe9edf7full, 0x9ea9a9884f3721a9ull, + 0xa82a2a6754824d2aull, 0xd6bbbb0a6b6db1bbull, 0x23c1c1879fe246c1ull, 0x515353f1a602a253ull, + 0x57dcdc72a58baedcull, 0x2c0b0b531627580bull, 0x4e9d9d0127d39c9dull, 0xad6c6c2bd8c1476cull, + 0xc43131a462f59531ull, 0xcd7474f3e8b98774ull, 0xfff6f615f109e3f6ull, 0x0546464c8c430a46ull, + 0x8aacaca5452609acull, 0x1e8989b50f973c89ull, 0x501414b42844a014ull, 0xa3e1e1badf425be1ull, + 0x581616a62c4eb016ull, 0xe83a3af774d2cd3aull, 0xb9696906d2d06f69ull, 0x24090941122d4809ull, + 0xdd7070d7e0ada770ull, 0xe2b6b66f7154d9b6ull, 0x67d0d01ebdb7ced0ull, 0x93ededd6c77e3bedull, + 0x17cccce285db2eccull, 0x1542426884572a42ull, 0x5a98982c2dc2b498ull, 0xaaa4a4ed550e49a4ull, + 0xa028287550885d28ull, 0x6d5c5c86b831da5cull, 0xc7f8f86bed3f93f8ull, 0x228686c211a44486ull + }, + { + 0x1818d83078c01860ull, 0x23232646af05238cull, 0xc6c6b891f97ec63full, 0xe8e8fbcd6f13e887ull, + 0x8787cb13a14c8726ull, 0xb8b8116d62a9b8daull, 0x0101090205080104ull, 0x4f4f0d9e6e424f21ull, + 0x36369b6ceead36d8ull, 0xa6a6ff510459a6a2ull, 0xd2d20cb9bdded26full, 0xf5f50ef706fbf5f3ull, + 0x797996f280ef79f9ull, 0x6f6f30dece5f6fa1ull, 0x91916d3feffc917eull, 0x5252f8a407aa5255ull, + 0x606047c0fd27609dull, 0xbcbc35657689bccaull, 0x9b9b372bcdac9b56ull, 0x8e8e8a018c048e02ull, + 0xa3a3d25b1571a3b6ull, 0x0c0c6c183c600c30ull, 0x7b7b84f68aff7bf1ull, 0x3535806ae1b535d4ull, + 0x1d1df53a69e81d74ull, 0xe0e0b3dd4753e0a7ull, 0xd7d721b3acf6d77bull, 0xc2c29c99ed5ec22full, + 0x2e2e435c966d2eb8ull, 0x4b4b29967a624b31ull, 0xfefe5de121a3fedfull, 0x5757d5ae16825741ull, + 0x1515bd2a41a81554ull, 0x7777e8eeb69f77c1ull, 0x3737926eeba537dcull, 0xe5e59ed7567be5b3ull, + 0x9f9f1323d98c9f46ull, 0xf0f023fd17d3f0e7ull, 0x4a4a20947f6a4a35ull, 0xdada44a9959eda4full, + 0x5858a2b025fa587dull, 0xc9c9cf8fca06c903ull, 0x29297c528d5529a4ull, 0x0a0a5a1422500a28ull, + 0xb1b1507f4fe1b1feull, 0xa0a0c95d1a69a0baull, 0x6b6b14d6da7f6bb1ull, 0x8585d917ab5c852eull, + 0xbdbd3c677381bdceull, 0x5d5d8fba34d25d69ull, 0x1010902050801040ull, 0xf4f407f503f3f4f7ull, + 0xcbcbdd8bc016cb0bull, 0x3e3ed37cc6ed3ef8ull, 0x05052d0a11280514ull, 0x676778cee61f6781ull, + 0xe4e497d55373e4b7ull, 0x2727024ebb25279cull, 0x4141738258324119ull, 0x8b8ba70b9d2c8b16ull, + 0xa7a7f6530151a7a6ull, 0x7d7db2fa94cf7de9ull, 0x95954937fbdc956eull, 0xd8d856ad9f8ed847ull, + 0xfbfb70eb308bfbcbull, 0xeeeecdc17123ee9full, 0x7c7cbbf891c77cedull, 0x666671cce3176685ull, + 0xdddd7ba78ea6dd53ull, 0x1717af2e4bb8175cull, 0x4747458e46024701ull, 0x9e9e1a21dc849e42ull, + 0xcacad489c51eca0full, 0x2d2d585a99752db4ull, 0xbfbf2e637991bfc6ull, 0x07073f0e1b38071cull, + 0xadadac472301ad8eull, 0x5a5ab0b42fea5a75ull, 0x8383ef1bb56c8336ull, 0x3333b666ff8533ccull, + 0x63635cc6f23f6391ull, 0x020212040a100208ull, 0xaaaa93493839aa92ull, 0x7171dee2a8af71d9ull, + 0xc8c8c68dcf0ec807ull, 0x1919d1327dc81964ull, 0x49493b9270724939ull, 0xd9d95faf9a86d943ull, + 0xf2f231f91dc3f2efull, 0xe3e3a8db484be3abull, 0x5b5bb9b62ae25b71ull, 0x8888bc0d9234881aull, + 0x9a9a3e29c8a49a52ull, 0x26260b4cbe2d2698ull, 0x3232bf64fa8d32c8ull, 0xb0b0597d4ae9b0faull, + 0xe9e9f2cf6a1be983ull, 0x0f0f771e33780f3cull, 0xd5d533b7a6e6d573ull, 0x8080f41dba74803aull, + 0xbebe27617c99bec2ull, 0xcdcdeb87de26cd13ull, 0x34348968e4bd34d0ull, 0x48483290757a483dull, + 0xffff54e324abffdbull, 0x7a7a8df48ff77af5ull, 0x9090643deaf4907aull, 0x5f5f9dbe3ec25f61ull, + 0x20203d40a01d2080ull, 0x68680fd0d56768bdull, 0x1a1aca3472d01a68ull, 0xaeaeb7412c19ae82ull, + 0xb4b47d755ec9b4eaull, 0x5454cea8199a544dull, 0x93937f3be5ec9376ull, 0x22222f44aa0d2288ull, + 0x646463c8e907648dull, 0xf1f12aff12dbf1e3ull, 0x7373cce6a2bf73d1ull, 0x121282245a901248ull, + 0x40407a805d3a401dull, 0x0808481028400820ull, 0xc3c3959be856c32bull, 0xececdfc57b33ec97ull, + 0xdbdb4dab9096db4bull, 0xa1a1c05f1f61a1beull, 0x8d8d9107831c8d0eull, 0x3d3dc87ac9f53df4ull, + 0x97975b33f1cc9766ull, 0x0000000000000000ull, 0xcfcff983d436cf1bull, 0x2b2b6e5687452bacull, + 0x7676e1ecb39776c5ull, 0x8282e619b0648232ull, 0xd6d628b1a9fed67full, 0x1b1bc33677d81b6cull, + 0xb5b574775bc1b5eeull, 0xafafbe432911af86ull, 0x6a6a1dd4df776ab5ull, 0x5050eaa00dba505dull, + 0x4545578a4c124509ull, 0xf3f338fb18cbf3ebull, 0x3030ad60f09d30c0ull, 0xefefc4c3742bef9bull, + 0x3f3fda7ec3e53ffcull, 0x5555c7aa1c925549ull, 0xa2a2db591079a2b2ull, 0xeaeae9c96503ea8full, + 0x65656acaec0f6589ull, 0xbaba036968b9bad2ull, 0x2f2f4a5e93652fbcull, 0xc0c08e9de74ec027ull, + 0xdede60a181bede5full, 0x1c1cfc386ce01c70ull, 0xfdfd46e72ebbfdd3ull, 0x4d4d1f9a64524d29ull, + 0x92927639e0e49272ull, 0x7575faeabc8f75c9ull, 0x0606360c1e300618ull, 0x8a8aae0998248a12ull, + 0xb2b24b7940f9b2f2ull, 0xe6e685d15963e6bfull, 0x0e0e7e1c36700e38ull, 0x1f1fe73e63f81f7cull, + 0x626255c4f7376295ull, 0xd4d43ab5a3eed477ull, 0xa8a8814d3229a89aull, 0x96965231f4c49662ull, + 0xf9f962ef3a9bf9c3ull, 0xc5c5a397f666c533ull, 0x2525104ab1352594ull, 0x5959abb220f25979ull, + 0x8484d015ae54842aull, 0x7272c5e4a7b772d5ull, 0x3939ec72ddd539e4ull, 0x4c4c1698615a4c2dull, + 0x5e5e94bc3bca5e65ull, 0x78789ff085e778fdull, 0x3838e570d8dd38e0ull, 0x8c8c980586148c0aull, + 0xd1d117bfb2c6d163ull, 0xa5a5e4570b41a5aeull, 0xe2e2a1d94d43e2afull, 0x61614ec2f82f6199ull, + 0xb3b3427b45f1b3f6ull, 0x21213442a5152184ull, 0x9c9c0825d6949c4aull, 0x1e1eee3c66f01e78ull, + 0x4343618652224311ull, 0xc7c7b193fc76c73bull, 0xfcfc4fe52bb3fcd7ull, 0x0404240814200410ull, + 0x5151e3a208b25159ull, 0x9999252fc7bc995eull, 0x6d6d22dac44f6da9ull, 0x0d0d651a39680d34ull, + 0xfafa79e93583facfull, 0xdfdf69a384b6df5bull, 0x7e7ea9fc9bd77ee5ull, 0x24241948b43d2490ull, + 0x3b3bfe76d7c53becull, 0xabab9a4b3d31ab96ull, 0xcecef081d13ece1full, 0x1111992255881144ull, + 0x8f8f8303890c8f06ull, 0x4e4e049c6b4a4e25ull, 0xb7b7667351d1b7e6ull, 0xebebe0cb600beb8bull, + 0x3c3cc178ccfd3cf0ull, 0x8181fd1fbf7c813eull, 0x94944035fed4946aull, 0xf7f71cf30cebf7fbull, + 0xb9b9186f67a1b9deull, 0x13138b265f98134cull, 0x2c2c51589c7d2cb0ull, 0xd3d305bbb8d6d36bull, + 0xe7e78cd35c6be7bbull, 0x6e6e39dccb576ea5ull, 0xc4c4aa95f36ec437ull, 0x03031b060f18030cull, + 0x5656dcac138a5645ull, 0x44445e88491a440dull, 0x7f7fa0fe9edf7fe1ull, 0xa9a9884f3721a99eull, + 0x2a2a6754824d2aa8ull, 0xbbbb0a6b6db1bbd6ull, 0xc1c1879fe246c123ull, 0x5353f1a602a25351ull, + 0xdcdc72a58baedc57ull, 0x0b0b531627580b2cull, 0x9d9d0127d39c9d4eull, 0x6c6c2bd8c1476cadull, + 0x3131a462f59531c4ull, 0x7474f3e8b98774cdull, 0xf6f615f109e3f6ffull, 0x46464c8c430a4605ull, + 0xacaca5452609ac8aull, 0x8989b50f973c891eull, 0x1414b42844a01450ull, 0xe1e1badf425be1a3ull, + 0x1616a62c4eb01658ull, 0x3a3af774d2cd3ae8ull, 0x696906d2d06f69b9ull, 0x090941122d480924ull, + 0x7070d7e0ada770ddull, 0xb6b66f7154d9b6e2ull, 0xd0d01ebdb7ced067ull, 0xededd6c77e3bed93ull, + 0xcccce285db2ecc17ull, 0x42426884572a4215ull, 0x98982c2dc2b4985aull, 0xa4a4ed550e49a4aaull, + 0x28287550885d28a0ull, 0x5c5c86b831da5c6dull, 0xf8f86bed3f93f8c7ull, 0x8686c211a4448622ull + }, + { + 0x18d83078c0186018ull, 0x232646af05238c23ull, 0xc6b891f97ec63fc6ull, 0xe8fbcd6f13e887e8ull, + 0x87cb13a14c872687ull, 0xb8116d62a9b8dab8ull, 0x0109020508010401ull, 0x4f0d9e6e424f214full, + 0x369b6ceead36d836ull, 0xa6ff510459a6a2a6ull, 0xd20cb9bdded26fd2ull, 0xf50ef706fbf5f3f5ull, + 0x7996f280ef79f979ull, 0x6f30dece5f6fa16full, 0x916d3feffc917e91ull, 0x52f8a407aa525552ull, + 0x6047c0fd27609d60ull, 0xbc35657689bccabcull, 0x9b372bcdac9b569bull, 0x8e8a018c048e028eull, + 0xa3d25b1571a3b6a3ull, 0x0c6c183c600c300cull, 0x7b84f68aff7bf17bull, 0x35806ae1b535d435ull, + 0x1df53a69e81d741dull, 0xe0b3dd4753e0a7e0ull, 0xd721b3acf6d77bd7ull, 0xc29c99ed5ec22fc2ull, + 0x2e435c966d2eb82eull, 0x4b29967a624b314bull, 0xfe5de121a3fedffeull, 0x57d5ae1682574157ull, + 0x15bd2a41a8155415ull, 0x77e8eeb69f77c177ull, 0x37926eeba537dc37ull, 0xe59ed7567be5b3e5ull, + 0x9f1323d98c9f469full, 0xf023fd17d3f0e7f0ull, 0x4a20947f6a4a354aull, 0xda44a9959eda4fdaull, + 0x58a2b025fa587d58ull, 0xc9cf8fca06c903c9ull, 0x297c528d5529a429ull, 0x0a5a1422500a280aull, + 0xb1507f4fe1b1feb1ull, 0xa0c95d1a69a0baa0ull, 0x6b14d6da7f6bb16bull, 0x85d917ab5c852e85ull, + 0xbd3c677381bdcebdull, 0x5d8fba34d25d695dull, 0x1090205080104010ull, 0xf407f503f3f4f7f4ull, + 0xcbdd8bc016cb0bcbull, 0x3ed37cc6ed3ef83eull, 0x052d0a1128051405ull, 0x6778cee61f678167ull, + 0xe497d55373e4b7e4ull, 0x27024ebb25279c27ull, 0x4173825832411941ull, 0x8ba70b9d2c8b168bull, + 0xa7f6530151a7a6a7ull, 0x7db2fa94cf7de97dull, 0x954937fbdc956e95ull, 0xd856ad9f8ed847d8ull, + 0xfb70eb308bfbcbfbull, 0xeecdc17123ee9feeull, 0x7cbbf891c77ced7cull, 0x6671cce317668566ull, + 0xdd7ba78ea6dd53ddull, 0x17af2e4bb8175c17ull, 0x47458e4602470147ull, 0x9e1a21dc849e429eull, + 0xcad489c51eca0fcaull, 0x2d585a99752db42dull, 0xbf2e637991bfc6bfull, 0x073f0e1b38071c07ull, + 0xadac472301ad8eadull, 0x5ab0b42fea5a755aull, 0x83ef1bb56c833683ull, 0x33b666ff8533cc33ull, + 0x635cc6f23f639163ull, 0x0212040a10020802ull, 0xaa93493839aa92aaull, 0x71dee2a8af71d971ull, + 0xc8c68dcf0ec807c8ull, 0x19d1327dc8196419ull, 0x493b927072493949ull, 0xd95faf9a86d943d9ull, + 0xf231f91dc3f2eff2ull, 0xe3a8db484be3abe3ull, 0x5bb9b62ae25b715bull, 0x88bc0d9234881a88ull, + 0x9a3e29c8a49a529aull, 0x260b4cbe2d269826ull, 0x32bf64fa8d32c832ull, 0xb0597d4ae9b0fab0ull, + 0xe9f2cf6a1be983e9ull, 0x0f771e33780f3c0full, 0xd533b7a6e6d573d5ull, 0x80f41dba74803a80ull, + 0xbe27617c99bec2beull, 0xcdeb87de26cd13cdull, 0x348968e4bd34d034ull, 0x483290757a483d48ull, + 0xff54e324abffdbffull, 0x7a8df48ff77af57aull, 0x90643deaf4907a90ull, 0x5f9dbe3ec25f615full, + 0x203d40a01d208020ull, 0x680fd0d56768bd68ull, 0x1aca3472d01a681aull, 0xaeb7412c19ae82aeull, + 0xb47d755ec9b4eab4ull, 0x54cea8199a544d54ull, 0x937f3be5ec937693ull, 0x222f44aa0d228822ull, + 0x6463c8e907648d64ull, 0xf12aff12dbf1e3f1ull, 0x73cce6a2bf73d173ull, 0x1282245a90124812ull, + 0x407a805d3a401d40ull, 0x0848102840082008ull, 0xc3959be856c32bc3ull, 0xecdfc57b33ec97ecull, + 0xdb4dab9096db4bdbull, 0xa1c05f1f61a1bea1ull, 0x8d9107831c8d0e8dull, 0x3dc87ac9f53df43dull, + 0x975b33f1cc976697ull, 0x0000000000000000ull, 0xcff983d436cf1bcfull, 0x2b6e5687452bac2bull, + 0x76e1ecb39776c576ull, 0x82e619b064823282ull, 0xd628b1a9fed67fd6ull, 0x1bc33677d81b6c1bull, + 0xb574775bc1b5eeb5ull, 0xafbe432911af86afull, 0x6a1dd4df776ab56aull, 0x50eaa00dba505d50ull, + 0x45578a4c12450945ull, 0xf338fb18cbf3ebf3ull, 0x30ad60f09d30c030ull, 0xefc4c3742bef9befull, + 0x3fda7ec3e53ffc3full, 0x55c7aa1c92554955ull, 0xa2db591079a2b2a2ull, 0xeae9c96503ea8feaull, + 0x656acaec0f658965ull, 0xba036968b9bad2baull, 0x2f4a5e93652fbc2full, 0xc08e9de74ec027c0ull, + 0xde60a181bede5fdeull, 0x1cfc386ce01c701cull, 0xfd46e72ebbfdd3fdull, 0x4d1f9a64524d294dull, + 0x927639e0e4927292ull, 0x75faeabc8f75c975ull, 0x06360c1e30061806ull, 0x8aae0998248a128aull, + 0xb24b7940f9b2f2b2ull, 0xe685d15963e6bfe6ull, 0x0e7e1c36700e380eull, 0x1fe73e63f81f7c1full, + 0x6255c4f737629562ull, 0xd43ab5a3eed477d4ull, 0xa8814d3229a89aa8ull, 0x965231f4c4966296ull, + 0xf962ef3a9bf9c3f9ull, 0xc5a397f666c533c5ull, 0x25104ab135259425ull, 0x59abb220f2597959ull, + 0x84d015ae54842a84ull, 0x72c5e4a7b772d572ull, 0x39ec72ddd539e439ull, 0x4c1698615a4c2d4cull, + 0x5e94bc3bca5e655eull, 0x789ff085e778fd78ull, 0x38e570d8dd38e038ull, 0x8c980586148c0a8cull, + 0xd117bfb2c6d163d1ull, 0xa5e4570b41a5aea5ull, 0xe2a1d94d43e2afe2ull, 0x614ec2f82f619961ull, + 0xb3427b45f1b3f6b3ull, 0x213442a515218421ull, 0x9c0825d6949c4a9cull, 0x1eee3c66f01e781eull, + 0x4361865222431143ull, 0xc7b193fc76c73bc7ull, 0xfc4fe52bb3fcd7fcull, 0x0424081420041004ull, + 0x51e3a208b2515951ull, 0x99252fc7bc995e99ull, 0x6d22dac44f6da96dull, 0x0d651a39680d340dull, + 0xfa79e93583facffaull, 0xdf69a384b6df5bdfull, 0x7ea9fc9bd77ee57eull, 0x241948b43d249024ull, + 0x3bfe76d7c53bec3bull, 0xab9a4b3d31ab96abull, 0xcef081d13ece1fceull, 0x1199225588114411ull, + 0x8f8303890c8f068full, 0x4e049c6b4a4e254eull, 0xb7667351d1b7e6b7ull, 0xebe0cb600beb8bebull, + 0x3cc178ccfd3cf03cull, 0x81fd1fbf7c813e81ull, 0x944035fed4946a94ull, 0xf71cf30cebf7fbf7ull, + 0xb9186f67a1b9deb9ull, 0x138b265f98134c13ull, 0x2c51589c7d2cb02cull, 0xd305bbb8d6d36bd3ull, + 0xe78cd35c6be7bbe7ull, 0x6e39dccb576ea56eull, 0xc4aa95f36ec437c4ull, 0x031b060f18030c03ull, + 0x56dcac138a564556ull, 0x445e88491a440d44ull, 0x7fa0fe9edf7fe17full, 0xa9884f3721a99ea9ull, + 0x2a6754824d2aa82aull, 0xbb0a6b6db1bbd6bbull, 0xc1879fe246c123c1ull, 0x53f1a602a2535153ull, + 0xdc72a58baedc57dcull, 0x0b531627580b2c0bull, 0x9d0127d39c9d4e9dull, 0x6c2bd8c1476cad6cull, + 0x31a462f59531c431ull, 0x74f3e8b98774cd74ull, 0xf615f109e3f6fff6ull, 0x464c8c430a460546ull, + 0xaca5452609ac8aacull, 0x89b50f973c891e89ull, 0x14b42844a0145014ull, 0xe1badf425be1a3e1ull, + 0x16a62c4eb0165816ull, 0x3af774d2cd3ae83aull, 0x6906d2d06f69b969ull, 0x0941122d48092409ull, + 0x70d7e0ada770dd70ull, 0xb66f7154d9b6e2b6ull, 0xd01ebdb7ced067d0ull, 0xedd6c77e3bed93edull, + 0xcce285db2ecc17ccull, 0x426884572a421542ull, 0x982c2dc2b4985a98ull, 0xa4ed550e49a4aaa4ull, + 0x287550885d28a028ull, 0x5c86b831da5c6d5cull, 0xf86bed3f93f8c7f8ull, 0x86c211a444862286ull + } +}; + +} // namespace detail + +} // namespace digestpp + +#endif \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/detail/echo_provider.hpp b/ext/include/digestpp/algorithm/detail/echo_provider.hpp new file mode 100644 index 0000000..235f17b --- /dev/null +++ b/ext/include/digestpp/algorithm/detail/echo_provider.hpp @@ -0,0 +1,284 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_PROVIDERS_ECHO_HPP +#define DIGESTPP_PROVIDERS_ECHO_HPP + +#include "../../detail/functions.hpp" +#include "../../detail/absorb_data.hpp" +#include "../../detail/validate_hash_size.hpp" +#include "constants/echo_constants.hpp" +#include + +namespace digestpp +{ + +namespace detail +{ + +namespace echo_functions +{ + static inline void shift_rows(uint64_t* w) + { + std::swap(w[2], w[10]); + std::swap(w[3], w[11]); + std::swap(w[4], w[20]); + std::swap(w[5], w[21]); + std::swap(w[6], w[30]); + std::swap(w[7], w[31]); + std::swap(w[12], w[28]); + std::swap(w[13], w[29]); + std::swap(w[22], w[14]); + std::swap(w[23], w[15]); + std::swap(w[30], w[14]); + std::swap(w[31], w[15]); + std::swap(w[26], w[18]); + std::swap(w[27], w[19]); + std::swap(w[26], w[10]); + std::swap(w[27], w[11]); + } + + static inline void mix_columns(uint64_t* w) + { + for (int i = 0; i < 4; i++) + { + for (int j = 0; j < 2; j++) + { + const uint64_t firstbits = 0xfefefefefefefefeull; + const uint64_t lastbit = 0x0101010101010101ull; + size_t idx = i * 4 * 2 + j; + uint64_t a = w[idx]; + uint64_t b = w[idx + 2]; + uint64_t c = w[idx + 4]; + uint64_t d = w[idx + 6]; + + uint64_t dblA = ((a << 1) & firstbits) ^ (((a >> 7) & lastbit) * 0x1b); + uint64_t dblB = ((b << 1) & firstbits) ^ (((b >> 7) & lastbit) * 0x1b); + uint64_t dblC = ((c << 1) & firstbits) ^ (((c >> 7) & lastbit) * 0x1b); + uint64_t dblD = ((d << 1) & firstbits) ^ (((d >> 7) & lastbit) * 0x1b); + + uint64_t WT4 = w[idx] ^ w[idx + 2] ^ w[idx + 4] ^ w[idx + 6]; + + w[idx] = dblA ^ dblB ^ b ^ c ^ d; + w[idx + 2] = dblB ^ dblC ^ c ^ d ^ a; + w[idx + 4] = dblC ^ dblD ^ d ^ a ^ b; + w[idx + 6] = dblD ^ dblA ^ a ^ b ^ c; + } + } + } + + static inline void sub_words(uint64_t* w, uint64_t* salt, uint64_t& counter) + { + for (int r = 0; r < 16; r++) + { + size_t idx = r * 2; + size_t idx1 = r * 2 + 1; + uint32_t t0 = static_cast(counter) + ^ echo_constants::T[0][(unsigned char)(w[idx])] + ^ echo_constants::T[1][(unsigned char)(w[idx] >> 40)] + ^ echo_constants::T[2][(unsigned char)(w[idx1] >> 16)] + ^ echo_constants::T[3][(unsigned char)(w[idx1] >> 56)]; + uint32_t t1 = (counter >> 32) + ^ echo_constants::T[0][(unsigned char)(w[idx] >> 32)] + ^ echo_constants::T[1][(unsigned char)(w[idx1] >> 8)] + ^ echo_constants::T[2][(unsigned char)(w[idx1] >> 48)] + ^ echo_constants::T[3][(unsigned char)(w[idx] >> 24)]; + uint32_t t2 = echo_constants::T[0][(unsigned char)(w[idx1])] + ^ echo_constants::T[1][(unsigned char)(w[idx1] >> 40)] + ^ echo_constants::T[2][(unsigned char)(w[idx] >> 16)] + ^ echo_constants::T[3][(unsigned char)(w[idx] >> 56)]; + uint32_t t3 = echo_constants::T[0][(unsigned char)(w[idx1] >> 32)] + ^ echo_constants::T[1][(unsigned char)(w[idx] >> 8)] + ^ echo_constants::T[2][(unsigned char)(w[idx] >> 48)] + ^ echo_constants::T[3][(unsigned char)(w[idx1] >> 24)]; + + ++counter; + + w[idx] = static_cast(echo_constants::T[0][(unsigned char)(t0)] + ^ echo_constants::T[1][(unsigned char)(t1 >> 8)] + ^ echo_constants::T[2][(unsigned char)(t2 >> 16)] + ^ echo_constants::T[3][(unsigned char)(t3 >> 24)]) + ^ ( + static_cast(echo_constants::T[0][(unsigned char)(t1)] + ^ echo_constants::T[1][(unsigned char)(t2 >> 8)] + ^ echo_constants::T[2][(unsigned char)(t3 >> 16)] + ^ echo_constants::T[3][(unsigned char)(t0 >> 24)]) + << 32) + ^ salt[0]; + w[idx + 1] = static_cast(echo_constants::T[0][(unsigned char)(t2)] + ^ echo_constants::T[1][(unsigned char)(t3 >> 8)] + ^ echo_constants::T[2][(unsigned char)(t0 >> 16)] + ^ echo_constants::T[3][(unsigned char)(t1 >> 24)]) + ^ ( + static_cast(echo_constants::T[0][(unsigned char)(t3)] + ^ echo_constants::T[1][(unsigned char)(t0 >> 8)] + ^ echo_constants::T[2][(unsigned char)(t1 >> 16)] + ^ echo_constants::T[3][(unsigned char)(t2 >> 24)]) + << 32) + ^ salt[1]; + } + } + + + static inline void final256(uint64_t* h, uint64_t* w) + { + h[0] = h[0] ^ h[8] ^ h[16] ^ h[24] ^ w[0] ^ w[8] ^ w[16] ^ w[24]; + h[1] = h[1] ^ h[9] ^ h[17] ^ h[25] ^ w[1] ^ w[9] ^ w[17] ^ w[25]; + h[2] = h[2] ^ h[10] ^ h[18] ^ h[26] ^ w[2] ^ w[10] ^ w[18] ^ w[26]; + h[3] = h[3] ^ h[11] ^ h[19] ^ h[27] ^ w[3] ^ w[11] ^ w[19] ^ w[27]; + h[4] = h[4] ^ h[12] ^ h[20] ^ h[28] ^ w[4] ^ w[12] ^ w[20] ^ w[28]; + h[5] = h[5] ^ h[13] ^ h[21] ^ h[29] ^ w[5] ^ w[13] ^ w[21] ^ w[29]; + h[6] = h[6] ^ h[14] ^ h[22] ^ h[30] ^ w[6] ^ w[14] ^ w[22] ^ w[30]; + h[7] = h[7] ^ h[15] ^ h[23] ^ h[31] ^ w[7] ^ w[15] ^ w[23] ^ w[31]; + } + + static inline void final512(uint64_t* h, uint64_t* w) + { + h[0] = h[0] ^ h[16] ^ w[0] ^ w[16]; + h[1] = h[1] ^ h[17] ^ w[1] ^ w[17]; + h[2] = h[2] ^ h[18] ^ w[2] ^ w[18]; + h[3] = h[3] ^ h[19] ^ w[3] ^ w[19]; + h[4] = h[4] ^ h[20] ^ w[4] ^ w[20]; + h[5] = h[5] ^ h[21] ^ w[5] ^ w[21]; + h[6] = h[6] ^ h[22] ^ w[6] ^ w[22]; + h[7] = h[7] ^ h[23] ^ w[7] ^ w[23]; + h[8] = h[8] ^ h[24] ^ w[8] ^ w[24]; + h[9] = h[9] ^ h[25] ^ w[9] ^ w[25]; + h[10] = h[10] ^ h[26] ^ w[10] ^ w[26]; + h[11] = h[11] ^ h[27] ^ w[11] ^ w[27]; + h[12] = h[12] ^ h[28] ^ w[12] ^ w[28]; + h[13] = h[13] ^ h[29] ^ w[13] ^ w[29]; + h[14] = h[14] ^ h[30] ^ w[14] ^ w[30]; + h[15] = h[15] ^ h[31] ^ w[15] ^ w[31]; + } + +} + +class echo_provider +{ +public: + static const bool is_xof = false; + + echo_provider(size_t hashsize) + : hs(hashsize) + { + validate_hash_size(hashsize, 512); + zero_memory(salt); + } + + ~echo_provider() + { + clear(); + } + + inline void init() + { + pos = 0; + total = 0; + memset(&h[0], 0, sizeof(uint64_t)*32); + + for (int i = 0; i < (hs > 256 ? 8 : 4); i++) + { + h[2 * i] = hs; + h[2 * i + 1] = 0; + } + } + + inline void set_salt(const unsigned char* salt, size_t salt_len) + { + if (salt_len && salt_len != 16) + throw std::runtime_error("invalid salt length"); + + if (salt_len) + memcpy(this->salt.data(), salt, salt_len); + else + memset(this->salt.data(), 0, 16); + } + + inline void update(const unsigned char* data, size_t len) + { + detail::absorb_bytes(data, len, block_bytes(), block_bytes(), reinterpret_cast(h.data()) + 256 - block_bytes(), pos, total, + [this](const unsigned char* data, size_t num_blks) { transform(data, num_blks, true, block_bytes() * num_blks); }); + } + + inline void final(unsigned char* hash) + { + unsigned char* m = reinterpret_cast(h.data()) + 256 - block_bytes(); + total += pos * 8; + m[pos++] = 0x80; + size_t limit = block_bytes(); + if (pos > limit - 18) + { + if (limit != pos) + memset(&m[pos], 0, limit - pos); + transform(m, 1, true, 0); + pos = 0; + } + memset(&m[pos], 0, limit - 18 - pos); + uint16_t hsize = static_cast(hs); + memcpy(&m[limit - 18], &hsize, sizeof(hsize)); + memcpy(&m[limit - 16], &total, sizeof(total)); + memset(&m[limit - 8], 0, 8); + transform(m, 1, pos > 1, 0); + + memcpy(hash, reinterpret_cast(h.data()), hash_size() / 8); + } + + inline void clear() + { + zero_memory(h); + zero_memory(salt); + } + + inline size_t hash_size() const { return hs; } + +private: + inline size_t block_bytes() const { return (hs > 256 ? 1024 : 1536) / 8; } + + inline void transform(const unsigned char* mp, size_t num_blks, bool addedbits, uint64_t addtototal) + { + unsigned char* m = reinterpret_cast(h.data()) + 256 - block_bytes(); + for (size_t blk = 0; blk < num_blks; blk++) + { + uint64_t w[32]; + + uint64_t counter = 0; + if (addedbits) + { + uint64_t delta = std::min(addtototal, static_cast(block_bytes())); + counter = total + (blk * block_bytes() + delta) * 8; + addtototal -= delta; + + if (m != mp) + memcpy(m, mp + block_bytes() * blk, delta); + } + memcpy(w, h.data(), sizeof(w)); + int rounds = hs > 256 ? 10 : 8; + for (int l = 0; l < rounds; l++) + { + echo_functions::sub_words(w, salt.data(), counter); + echo_functions::shift_rows(w); + echo_functions::mix_columns(w); + } + + if (hs <= 256) + echo_functions::final256(h.data(), w); + else + echo_functions::final512(h.data(), w); + } + } + + std::array h; + std::array salt; + size_t hs; + size_t pos; + uint64_t total; + +}; + +} // namespace detail + +} // namespace digestpp + +#endif diff --git a/ext/include/digestpp/algorithm/detail/esch_provider.hpp b/ext/include/digestpp/algorithm/detail/esch_provider.hpp new file mode 100644 index 0000000..2387c6a --- /dev/null +++ b/ext/include/digestpp/algorithm/detail/esch_provider.hpp @@ -0,0 +1,211 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_PROVIDERS_ESCH_HPP +#define DIGESTPP_PROVIDERS_ESCH_HPP + +#include "../../detail/functions.hpp" +#include "../../detail/absorb_data.hpp" +#include "../../detail/validate_hash_size.hpp" +#include "constants/esch_constants.hpp" +#include + +namespace digestpp +{ + +namespace detail +{ + +namespace esch_functions +{ + +template +static inline void sparkle(std::array& H, int rounds, int ns) +{ + for(int s = 0; s < ns; s++) + { + H[1] ^= esch_constants::C[s % 8]; + H[3] ^= s; + for (int j = 0, px = 0, py = 1; j < rounds; j++, px += 2, py += 2) + { + H[px] += rotate_right(H[py], 31); + H[py] ^= rotate_right(H[px], 24); + H[px] ^= esch_constants::C[j]; + H[px] += rotate_right(H[py], 17); + H[py] ^= rotate_right(H[px], 17); + H[px] ^= esch_constants::C[j]; + H[px] += H[py]; + H[py] ^= rotate_right(H[px], 31); + H[px] ^= esch_constants::C[j]; + H[px] += rotate_right(H[py], 24); + H[py] ^= rotate_right(H[px], 16); + H[px] ^= esch_constants::C[j]; + } + uint32_t x = H[0] ^ H[2] ^ H[4]; + uint32_t y = H[1] ^ H[3] ^ H[5]; + if (rounds > 6) + { + x ^= H[6]; + y ^= H[7]; + } + x = rotate_right(x ^ (x << 16), 16); + y = rotate_right(y ^ (y << 16), 16); + + for (int i = 0, j = rounds; i < rounds; i+=2, j+=2) + { + H[j] ^= H[i] ^ y; + H[j + 1] ^= H[i + 1] ^ x; + } + x = H[rounds]; + y = H[rounds + 1]; + for (int i = 0; i < rounds - 2; i++) + { + H[i + rounds] = H[i]; + H[i] = H[i + rounds + 2]; + } + H[rounds * 2 - 2] = H[rounds - 2]; + H[rounds * 2 - 1] = H[rounds - 1]; + H[rounds - 2] = x; + H[rounds - 1] = y; + } +} + +} + +template +class esch_provider +{ +public: + static const bool is_xof = XOF; + + template::type* = nullptr> + esch_provider(size_t hashsize) + : hs(hashsize), squeezing(false) + { + static_assert(N == 384 || N == 512, "Esch only supports 384 and 512 bits state size"); + validate_hash_size(hashsize, {256, 384}); + } + + template::type* = nullptr> + esch_provider() : hs(N - 128), squeezing(false) + { + static_assert(N == 384 || N == 512, "Esch only supports 384 and 512 bits state size"); + } + + ~esch_provider() + { + clear(); + } + + inline void init() + { + pos = 0; + total = 0; + squeezing = false; + zero_memory(H); + zero_memory(m); + } + + inline void update(const unsigned char* data, size_t len) + { + detail::absorb_bytes(data, len, 16, 16 + 1, m.data(), pos, total, + [this](const unsigned char* data, size_t len) { transform(data, len, false); }); + } + + inline void squeeze(unsigned char* hash, size_t hss) + { + size_t processed = 0; + if (!squeezing) + { + total = 1; + squeezing = true; + if (pos < 16) + { + memset(&m[pos], 0, 16 - pos); + m[pos] = 0x80; + H[(hs+128)/64 - 1] ^= (XOF ? 0x5000000 : 0x1000000); + } + else + H[(hs+128)/64 - 1] ^= (XOF ? 0x6000000 : 0x2000000); + + transform(m.data(), 1, true); + } + else if (pos < 16) + { + size_t to_copy = std::min(hss, 16 - pos); + memcpy(hash, reinterpret_cast(H.data()) + pos, to_copy); + processed += to_copy; + pos += to_copy; + total = 0; + } + + while (processed < hss) + { + if (!total) + esch_functions::sparkle(H, hs > 256 ? 8 : 6, hs > 256 ? 8 : 7); + pos = std::min(hss - processed, static_cast(16)); + memcpy(hash + processed, H.data(), pos); + processed += pos; + total = 0; + } + } + + inline void final(unsigned char* hash) + { + return squeeze(hash, hs / 8); + } + + inline void clear() + { + zero_memory(H); + zero_memory(m); + } + + inline size_t hash_size() const { return hs; } + +private: + + inline void transform(const unsigned char* data, size_t num_blks, bool lastBlock) + { + for (size_t blk = 0; blk < num_blks; blk++) + { + uint32_t M[4]; + for (int i = 0; i < 4; i++) + M[i] = reinterpret_cast(data)[blk * 4 + i]; + uint32_t x = M[0] ^ M[2]; + uint32_t y = M[1] ^ M[3]; + x = rotate_right(x ^ (x << 16), 16); + y = rotate_right(y ^ (y << 16), 16); + H[0] = H[0] ^ M[0] ^ y; + H[1] = H[1] ^ M[1] ^ x; + H[2] = H[2] ^ M[2] ^ y; + H[3] = H[3] ^ M[3] ^ x; + H[4] ^= y; + H[5] ^= x; + if (hs > 256) + { + H[6] ^= y; + H[7] ^= x; + } + int steps = lastBlock ? 11 : 7; + if (hs > 256) + steps++; + esch_functions::sparkle(H, hs > 256 ? 8 : 6, steps); + } + } + + + std::array H; + std::array m; + size_t pos; + uint64_t total; + size_t hs; + bool squeezing; +}; + +} // namespace detail + +} // namespace digestpp + +#endif diff --git a/ext/include/digestpp/algorithm/detail/groestl_provider.hpp b/ext/include/digestpp/algorithm/detail/groestl_provider.hpp new file mode 100644 index 0000000..0aae4ff --- /dev/null +++ b/ext/include/digestpp/algorithm/detail/groestl_provider.hpp @@ -0,0 +1,202 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_PROVIDERS_GROESTL_HPP +#define DIGESTPP_PROVIDERS_GROESTL_HPP + +#include "../../detail/functions.hpp" +#include "../../detail/absorb_data.hpp" +#include "../../detail/validate_hash_size.hpp" +#include "constants/groestl_constants.hpp" +#include + +namespace digestpp +{ + +namespace detail +{ + +namespace groestl_functions +{ + template + static inline void roundP(uint64_t* x, uint64_t* y, uint64_t i) + { + for (int idx = 0; idx < R; idx++) + x[idx] ^= (static_cast(idx) << 4) ^ i; + + for (int c = R - 1; c >= 0; c--) + y[c] = groestl_constants::T[0][static_cast(x[(c + 0) % R])] + ^ groestl_constants::T[1][static_cast(x[(c + 1) % R] >> 8)] + ^ groestl_constants::T[2][static_cast(x[(c + 2) % R] >> 16)] + ^ groestl_constants::T[3][static_cast(x[(c + 3) % R] >> 24)] + ^ groestl_constants::T[4][static_cast(x[(c + 4) % R] >> 32)] + ^ groestl_constants::T[5][static_cast(x[(c + 5) % R] >> 40)] + ^ groestl_constants::T[6][static_cast(x[(c + 6) % R] >> 48)] + ^ groestl_constants::T[7][static_cast(x[(c + (R == 16 ? 11 : 7)) % R] >> 56)]; + } + + template + static inline void roundQ(uint64_t* x, uint64_t* y, uint64_t i) + { + for (int idx = 0; idx < R; idx++) + x[idx] ^= (0xffffffffffffffffull - (static_cast(idx) << 60)) ^ i; + + for (int c = R - 1; c >= 0; c--) + y[c] = groestl_constants::T[0][static_cast(x[(c + 1) % R])] + ^ groestl_constants::T[1][static_cast(x[(c + 3) % R] >> 8)] + ^ groestl_constants::T[2][static_cast(x[(c + 5) % R] >> 16)] + ^ groestl_constants::T[3][static_cast(x[(c + (R == 16 ? 11 : 7)) % R] >> 24)] + ^ groestl_constants::T[4][static_cast(x[(c + 0) % R] >> 32)] + ^ groestl_constants::T[5][static_cast(x[(c + 2) % R] >> 40)] + ^ groestl_constants::T[6][static_cast(x[(c + 4) % R] >> 48)] + ^ groestl_constants::T[7][static_cast(x[(c + 6) % R] >> 56)]; + } + + template + static inline void transform(uint64_t* h, const uint64_t* m) + { + uint64_t AQ1[R], AQ2[R], AP1[R], AP2[R]; + + for (int column = 0; column < R; column++) + { + AP1[column] = h[column] ^ m[column]; + AQ1[column] = m[column]; + } + + for (uint64_t r = 0; r < (R == 16 ? 14 : 10); r += 2) + { + roundP(AP1, AP2, r); + roundP(AP2, AP1, r + 1); + roundQ(AQ1, AQ2, r << 56); + roundQ(AQ2, AQ1, (r + 1ull) << 56); + } + + for (int column = 0; column < R; column++) + { + h[column] = AP1[column] ^ AQ1[column] ^ h[column]; + } + } + + template + static inline void outputTransform(uint64_t* h) + { + uint64_t t1[R]; + uint64_t t2[R]; + + for (int column = 0; column < R; column++) { + t1[column] = h[column]; + } + + for (uint64_t r = 0; r < (R == 16 ? 14 : 10); r += 2) { + roundP(t1, t2, r); + roundP(t2, t1, r+1); + } + + for (int column = 0; column < R; column++) { + h[column] ^= t1[column]; + } + } + +} + +class groestl_provider +{ +public: + static const bool is_xof = false; + + groestl_provider(size_t hashsize) + : hs(hashsize) + { + validate_hash_size(hashsize, 512); + } + + ~groestl_provider() + { + clear(); + } + + inline void init() + { + pos = 0; + total = 0; + memset(&h[0], 0, sizeof(uint64_t)*16); + uint64_t hs = hash_size(); + h[hs > 256 ? 15 : 7] = byteswap(hs); + } + + inline void update(const unsigned char* data, size_t len) + { + detail::absorb_bytes(data, len, block_bytes(), block_bytes(), m.data(), pos, total, + [this](const unsigned char* data, size_t len) { transform(data, len); }); + } + + inline void final(unsigned char* hash) + { + m[pos++] = 0x80; + total += pos * 8; + size_t limit = block_bytes(); + if (pos > limit - 8) + { + if (limit != pos) + memset(&m[pos], 0, limit - pos); + transform(m.data(), 1); + total += (block_bytes() - pos) * 8; + pos = 0; + } + memset(&m[pos], 0, limit - 8 - pos); + total += (block_bytes() - pos) * 8; + uint64_t mlen = byteswap(total / 8 / block_bytes()); + memcpy(&m[limit - 8], &mlen, 64 / 8); + transform(m.data(), 1); + outputTransform(); + + const unsigned char* s = reinterpret_cast(h.data()); + for (size_t i = limit - hash_size() / 8, j = 0; i < limit; i++, j++) { + hash[j] = s[i]; + } + } + + inline void clear() + { + zero_memory(h); + zero_memory(m); + } + + inline size_t hash_size() const { return hs; } + +private: + inline size_t block_bytes() const { return hs > 256 ? 128 : 64; } + + inline void outputTransform() + { + if (hs > 256) + groestl_functions::outputTransform<16>(&h[0]); + else + groestl_functions::outputTransform<8>(&h[0]); + } + + inline void transform(const unsigned char* mp, size_t num_blks) + { + for (size_t blk = 0; blk < num_blks; blk++) + { + if (hs > 256) + groestl_functions::transform<16>(&h[0], reinterpret_cast(mp + block_bytes() * blk)); + else + groestl_functions::transform<8>(&h[0], reinterpret_cast(mp + block_bytes() * blk)); + } + } + + std::array h; + std::array m; + size_t hs; + size_t pos; + uint64_t total; + +}; + +} // namespace detail + +} // namespace digestpp + +#endif \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/detail/jh_provider.hpp b/ext/include/digestpp/algorithm/detail/jh_provider.hpp new file mode 100644 index 0000000..599c2b8 --- /dev/null +++ b/ext/include/digestpp/algorithm/detail/jh_provider.hpp @@ -0,0 +1,214 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_PROVIDERS_JH_HPP +#define DIGESTPP_PROVIDERS_JH_HPP + +#include "../../detail/functions.hpp" +#include "../../detail/absorb_data.hpp" +#include "../../detail/validate_hash_size.hpp" +#include "constants/jh_constants.hpp" +#include + +namespace digestpp +{ + +namespace detail +{ + +namespace jh_functions +{ + static inline void bitswap(uint64_t& x, uint64_t mask, int shift) + { + x = ((x & mask) << shift) | ((x & ~mask) >> shift); + } + + static inline void bitswap(std::array& H, uint64_t mask, int shift) + { + bitswap(H[2], mask, shift); + bitswap(H[3], mask, shift); + bitswap(H[6], mask, shift); + bitswap(H[7], mask, shift); + bitswap(H[10], mask, shift); + bitswap(H[11], mask, shift); + bitswap(H[14], mask, shift); + bitswap(H[15], mask, shift); + } + + static inline void Sbitsli(uint64_t& x0a, uint64_t& x0b, uint64_t& x1a, uint64_t& x1b, uint64_t& x2a, uint64_t& x2b, + uint64_t& x3a, uint64_t& x3b, uint64_t ca, uint64_t cb) + { + x3a = ~x3a; + x3b = ~x3b; + x0a ^= (ca & ~x2a); + x0b ^= (cb & ~x2b); + uint64_t ta = ca ^ (x0a & x1a); + uint64_t tb = cb ^ (x0b & x1b); + x0a ^= (x2a & x3a); + x0b ^= (x2b & x3b); + x3a ^= (~x1a & x2a); + x3b ^= (~x1b & x2b); + x1a ^= (x0a & x2a); + x1b ^= (x0b & x2b); + x2a ^= (x0a & ~x3a); + x2b ^= (x0b & ~x3b); + x0a ^= (x1a | x3a); + x0b ^= (x1b | x3b); + x3a ^= (x1a & x2a); + x3b ^= (x1b & x2b); + x1a ^= (ta & x0a); + x1b ^= (tb & x0b); + x2a ^= ta; + x2b ^= tb; + } + + static inline void Lbitsli(std::array& H) + { + H[2] ^= H[4]; + H[3] ^= H[5]; + H[6] ^= H[8]; + H[7] ^= H[9]; + H[10] ^= H[12] ^ H[0]; + H[11] ^= H[13] ^ H[1]; + H[14] ^= H[0]; + H[15] ^= H[1]; + H[0] ^= H[6]; + H[1] ^= H[7]; + H[4] ^= H[10]; + H[5] ^= H[11]; + H[8] ^= H[14] ^ H[2]; + H[9] ^= H[15] ^ H[3]; + H[12] ^= H[2]; + H[13] ^= H[3]; + } + + static inline void round(std::array& H, int r, uint64_t mask, int shift) + { + jh_functions::Sbitsli(H[0], H[1], H[4], H[5], H[8], H[9], H[12], H[13], + jh_constants::C[r * 4 + 0], jh_constants::C[r * 4 + 1]); + jh_functions::Sbitsli(H[2], H[3], H[6], H[7], H[10], H[11], H[14], H[15], + jh_constants::C[r * 4 + 2], jh_constants::C[r * 4 + 3]); + jh_functions::Lbitsli(H); + if (shift) + jh_functions::bitswap(H, mask, shift); + } +} + +class jh_provider +{ +public: + static const bool is_xof = false; + + jh_provider(size_t hashsize = 512) + : hs(hashsize) + { + validate_hash_size(hashsize, 512); + } + + ~jh_provider() + { + clear(); + } + + inline void init() + { + pos = 0; + total = 0; + + zero_memory(H); + H[0] = byteswap(static_cast(hs)); + + unsigned char msg[64]; + memset(msg, 0, sizeof(msg)); + transform(msg, 1); + } + + inline void update(const unsigned char* data, size_t len) + { + detail::absorb_bytes(data, len, 64, 64, m.data(), pos, total, + [this](const unsigned char* data, size_t len) { transform(data, len); }); + } + + inline void final(unsigned char* hash) + { + total += pos * 8; + m[pos++] = 0x80; + if (pos > 1) + { + if (pos != 64) + memset(&m[pos], 0, 64 - pos); + transform(&m[0], 1); + pos = 0; + } + memset(&m[0] + pos, 0, 56 - pos); + uint64_t mlen = byteswap(total); + memcpy(&m[0] + (64 - 8), &mlen, 64 / 8); + transform(&m[0], 1); + + memcpy(hash, reinterpret_cast(H.data()) + 128 - hash_size() / 8, hash_size() / 8); + } + + inline void clear() + { + zero_memory(H); + zero_memory(m); + } + + inline size_t hash_size() const { return hs; } + +private: + inline void transform(const unsigned char* mp, size_t num_blks) + { + for (uint64_t blk = 0; blk < num_blks; blk++) + { + const uint64_t* M = (const uint64_t*)(((const unsigned char*)mp) + blk * 64); + H[0] ^= M[0]; + H[1] ^= M[1]; + H[2] ^= M[2]; + H[3] ^= M[3]; + H[4] ^= M[4]; + H[5] ^= M[5]; + H[6] ^= M[6]; + H[7] ^= M[7]; + + // partially unroll + for (int r = 0; r < 42; r += 7) + { + jh_functions::round(H, r, 0x5555555555555555ULL, 1); + jh_functions::round(H, r + 1, 0x3333333333333333ULL, 2); + jh_functions::round(H, r + 2, 0x0f0f0f0f0f0f0f0fULL, 4); + jh_functions::round(H, r + 3, 0x00ff00ff00ff00ffULL, 8); + jh_functions::round(H, r + 4, 0x0000ffff0000ffffULL, 16); + jh_functions::round(H, r + 5, 0x00000000ffffffffULL, 32); + jh_functions::round(H, r + 6, 0, 0); + + std::swap(H[2], H[3]); + std::swap(H[6], H[7]); + std::swap(H[10], H[11]); + std::swap(H[14], H[15]); + } + + H[8] ^= M[0]; + H[9] ^= M[1]; + H[10] ^= M[2]; + H[11] ^= M[3]; + H[12] ^= M[4]; + H[13] ^= M[5]; + H[14] ^= M[6]; + H[15] ^= M[7]; + } + } + + std::array H; + std::array m; + size_t hs; + size_t pos; + uint64_t total; +}; + +} // namespace detail + +} // namespace digestpp + +#endif \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/detail/k12m14_provider.hpp b/ext/include/digestpp/algorithm/detail/k12m14_provider.hpp new file mode 100644 index 0000000..6aefa09 --- /dev/null +++ b/ext/include/digestpp/algorithm/detail/k12m14_provider.hpp @@ -0,0 +1,139 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_PROVIDERS_K12M14_HPP +#define DIGESTPP_PROVIDERS_K12M14_HPP + +#include "../../detail/functions.hpp" +#include "../../detail/absorb_data.hpp" +#include "shake_provider.hpp" +#include + +namespace digestpp +{ + +namespace detail +{ + +template +class k12m14_provider +{ +public: + static const bool is_xof = true; + + k12m14_provider() + { + static_assert(B == 128 || B == 256, "K12M14 only supports 128 and 256 bits"); + } + + ~k12m14_provider() + { + clear(); + } + + inline void set_customization(const std::string& customization) + { + S = customization; + } + + inline void init() + { + main.init(); + pos = 0; + total = 0; + chunk = 0; + squeezing = false; + } + + inline void update(const unsigned char* data, size_t len) + { + detail::absorb_bytes(data, len, m.size(), m.size(), m.data(), pos, total, + [this](const unsigned char* data, size_t len) { transform(data, len, len * 8192); }); + } + + inline void squeeze(unsigned char* hash, size_t hs) + { + if (!squeezing) + { + unsigned char buf[B / 4]; + size_t len = shake_functions::right_encode(S.length(), buf, true); + if (!S.empty()) + update(reinterpret_cast(S.data()), S.length()); + update(buf, len); + if (pos) + { + if (!chunk) + { + main.update(m.data(), pos); + main.set_suffix(0x07); + } + else + { + child.update(m.data(), pos); + child.squeeze(buf, B / 4); + main.update(buf, B / 4); + main.set_suffix(0x06); + len = shake_functions::right_encode(chunk, buf, true); + main.update(buf, len); + main.update(reinterpret_cast("\xFF\xFF"), 2); + } + } + squeezing = true; + } + main.squeeze(hash, hs); + } + + inline void transform(const unsigned char* data, uint64_t num_blks, size_t reallen) + { + (void)reallen; + + for (uint64_t blk = 0; blk < num_blks; blk++) + { + if (!chunk) + { + main.update(data, 8192); + main.update(reinterpret_cast("\x03\x00\x00\x00\x00\x00\x00\x00"), 8); + } + else + { + child.update(data, 8192); + unsigned char buf[B / 4]; + child.squeeze(buf, B / 4); + main.update(buf, B / 4); + } + + child.init(); + child.set_suffix(0x0b); + ++chunk; + data += 8192; + } + } + + + inline void clear() + { + main.clear(); + child.clear(); + zero_memory(m); + zero_memory(S); + S.clear(); + } + +private: + constexpr static size_t R = B == 128 ? 12 : 14; + shake_provider main; + shake_provider child; + std::array m; + std::string S; + size_t pos; + size_t total; + size_t chunk; + bool squeezing; +}; + +} // namespace detail + +} // namespace digestpp + +#endif // DIGESTPP_PROVIDERS_K12M14_HPP \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/detail/kmac_provider.hpp b/ext/include/digestpp/algorithm/detail/kmac_provider.hpp new file mode 100644 index 0000000..896544b --- /dev/null +++ b/ext/include/digestpp/algorithm/detail/kmac_provider.hpp @@ -0,0 +1,126 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_PROVIDERS_KMAC_HPP +#define DIGESTPP_PROVIDERS_KMAC_HPP + +#include "shake_provider.hpp" + +namespace digestpp +{ + +namespace detail +{ + +namespace kmac_functions +{ + template + inline std::string bytepad(const std::string& str) + { + const size_t pad = B == 128 ? 168 : 136; + unsigned char buf[32]; + size_t len = shake_functions::left_encode(pad, buf); + std::string res(reinterpret_cast(buf), len); + len = shake_functions::left_encode(str.length() * 8, buf); + res.append(reinterpret_cast(buf), len); + res.append(str); + size_t delta = pad - res.size() % pad; + if (delta && delta != pad) + res.append(delta, '\x00'); + return res; + } + +} // namespace kmac_functions + + +template +class kmac_provider +{ +public: + static const bool is_xof = XOF; + + template::type* = nullptr> + kmac_provider(size_t hashsize) : hs(hashsize) + { + static_assert(B == 128 || B == 256, "KMAC only supports 128 and 256 bits"); + validate_hash_size(hashsize, SIZE_MAX); + set_key(""); + } + + template::type* = nullptr> + kmac_provider() : hs(0) + { + static_assert(B == 128 || B == 256, "KMAC only supports 128 and 256 bits"); + set_key(""); + } + + ~kmac_provider() + { + clear(); + } + + inline void set_key(const std::string& key) + { + K = kmac_functions::bytepad(key); + } + + inline void set_customization(const std::string& customization) + { + shake.set_customization(customization); + } + + inline void init() + { + squeezing = false; + shake.set_function_name("KMAC"); + shake.init(); + update(reinterpret_cast(K.data()), K.length()); + } + + inline void update(const unsigned char* data, size_t len) + { + shake.update(data, len); + } + + inline void squeeze(unsigned char* hash, size_t hs) + { + if (!squeezing) + { + unsigned char buf[32]; + size_t len = shake_functions::right_encode(!XOF ? hs * 8 : 0, buf, false); + update(buf, len); + squeezing = true; + } + shake.squeeze(hash, hs); + } + + inline void final(unsigned char* hash) + { + squeeze(hash, hs / 8); + } + + inline void clear() + { + shake.clear(); + zero_memory(K); + set_key(""); + } + + inline size_t hash_size() const + { + return hs; + } + +private: + std::string K; + size_t hs; + bool squeezing; + shake_provider shake; +}; + +} // namespace detail + +} // namespace digestpp + +#endif // DIGESTPP_PROVIDERS_KMAC_HPP \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/detail/kupyna_provider.hpp b/ext/include/digestpp/algorithm/detail/kupyna_provider.hpp new file mode 100644 index 0000000..cec5eb0 --- /dev/null +++ b/ext/include/digestpp/algorithm/detail/kupyna_provider.hpp @@ -0,0 +1,196 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_PROVIDERS_KUPYNA_HPP +#define DIGESTPP_PROVIDERS_KUPYNA_HPP + +#include "../../detail/functions.hpp" +#include "../../detail/absorb_data.hpp" +#include "../../detail/validate_hash_size.hpp" +#include "constants/kupyna_constants.hpp" +#include + +namespace digestpp +{ + +namespace detail +{ + +namespace kupyna_functions +{ + template + static inline void G(uint64_t* x, uint64_t* y) + { + for (int c = 0; c != R; ++c) + y[c] = kupyna_constants::T[0][static_cast(x[(c + R) % R])] + ^ kupyna_constants::T[1][static_cast(x[(c + R - 1) % R] >> 8)] + ^ kupyna_constants::T[2][static_cast(x[(c + R - 2) % R] >> 16)] + ^ kupyna_constants::T[3][static_cast(x[(c + R - 3) % R] >> 24)] + ^ kupyna_constants::T[4][static_cast(x[(c + R - 4) % R] >> 32)] + ^ kupyna_constants::T[5][static_cast(x[(c + R - 5) % R] >> 40)] + ^ kupyna_constants::T[6][static_cast(x[(c + R - 6) % R] >> 48)] + ^ kupyna_constants::T[7][static_cast(x[(c + R - (R == 16 ? 11 : 7)) % R] >> 56)]; + } + + template + static inline void roundP(uint64_t* x, uint64_t* y, uint64_t i) + { + for (int idx = 0; idx < R; idx++) + x[idx] ^= (static_cast(idx) << 4) ^ i; + + G(x, y); + } + + template + static inline void roundQ(uint64_t* x, uint64_t* y, uint64_t i) + { + for (int j = 0; j < R; ++j) + x[j] += (0x00F0F0F0F0F0F0F3ULL + ^ ((static_cast(((R - 1 - j) * 0x10) ^ static_cast(i))) << 56)); + + G(x, y); + } + + template + static inline void transform(uint64_t* h, const uint64_t* m) + { + uint64_t AQ1[R], AQ2[R], AP1[R], AP2[R]; + + for (int column = 0; column < R; column++) + { + AP1[column] = h[column] ^ m[column]; + AQ1[column] = m[column]; + } + + for (uint64_t r = 0; r < (R == 16 ? 14 : 10); r += 2) + { + roundP(AP1, AP2, r); + roundP(AP2, AP1, r + 1); + roundQ(AQ1, AQ2, r); + roundQ(AQ2, AQ1, r + 1); + } + + for (int column = 0; column < R; column++) + { + h[column] = AP1[column] ^ AQ1[column] ^ h[column]; + } + } + + template + static inline void outputTransform(uint64_t* h) + { + uint64_t t1[R]; + uint64_t t2[R]; + + for (int column = 0; column < R; column++) { + t1[column] = h[column]; + } + + for (uint64_t r = 0; r < (R == 16 ? 14 : 10); r += 2) { + roundP(t1, t2, r); + roundP(t2, t1, r+1); + } + + for (int column = 0; column < R; column++) { + h[column] ^= t1[column]; + } + } + +} + +class kupyna_provider +{ +public: + static const bool is_xof = false; + + kupyna_provider(size_t hashsize) + : hs(hashsize) + { + validate_hash_size(hashsize, { 256, 512 }); + } + + ~kupyna_provider() + { + clear(); + } + + inline void init() + { + pos = 0; + total = 0; + memset(&h[0], 0, sizeof(uint64_t)*16); + h[0] = block_bytes(); // state in bytes + } + + inline void update(const unsigned char* data, size_t len) + { + detail::absorb_bytes(data, len, block_bytes(), block_bytes(), m.data(), pos, total, + [this](const unsigned char* data, size_t len) { transform(data, len); }); + } + + inline void final(unsigned char* hash) + { + total += pos * 8; + m[pos++] = 0x80; + size_t limit = block_bytes(); + if (pos > limit - 12) + { + if (limit != pos) + memset(&m[pos], 0, limit - pos); + transform(m.data(), 1); + pos = 0; + } + memset(&m[pos], 0, limit - pos); + memcpy(&m[limit - 12], &total, sizeof(uint64_t)); + memset(&m[limit - 4], 0, 4); + + transform(m.data(), 1); + outputTransform(); + + memcpy(hash, reinterpret_cast(h.data()) + limit - hash_size() / 8, hash_size() / 8); + } + + inline void clear() + { + zero_memory(h); + zero_memory(m); + } + + inline size_t hash_size() const { return hs; } + +private: + inline size_t block_bytes() const { return hs > 256 ? 128 : 64; } + + inline void outputTransform() + { + if (hs > 256) + kupyna_functions::outputTransform<16>(&h[0]); + else + kupyna_functions::outputTransform<8>(&h[0]); + } + + inline void transform(const unsigned char* mp, size_t num_blks) + { + for (size_t blk = 0; blk < num_blks; blk++) + { + if (hs > 256) + kupyna_functions::transform<16>(&h[0], reinterpret_cast(mp + block_bytes() * blk)); + else + kupyna_functions::transform<8>(&h[0], reinterpret_cast(mp + block_bytes() * blk)); + } + } + + std::array h; + std::array m; + size_t hs; + size_t pos; + uint64_t total; + +}; + +} // namespace detail + +} // namespace digestpp + +#endif \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/detail/md5_provider.hpp b/ext/include/digestpp/algorithm/detail/md5_provider.hpp new file mode 100644 index 0000000..d429b0c --- /dev/null +++ b/ext/include/digestpp/algorithm/detail/md5_provider.hpp @@ -0,0 +1,198 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_PROVIDERS_MD5_HPP +#define DIGESTPP_PROVIDERS_MD5_HPP + +#include "../../detail/functions.hpp" +#include "../../detail/absorb_data.hpp" +#include "constants/md5_constants.hpp" +#include + +namespace digestpp +{ + +namespace detail +{ + +namespace md5_functions +{ + static inline void roundf(int round, uint32_t& a, uint32_t& b, uint32_t& c, uint32_t& d, const uint32_t* M) + { + a = b + rotate_left(a + (d ^ (b & (c ^ d))) + md5_constants::K[round] + M[round], + md5_constants::S[round]); + } + + static inline void roundg(int round, uint32_t& a, uint32_t& b, uint32_t& c, uint32_t& d, const uint32_t* M) + { + a = b + rotate_left(a + (c ^ (d & (b ^ c))) + md5_constants::K[round] + M[(5 * round + 1) % 16], + md5_constants::S[round]); + } + + static inline void roundh(int round, uint32_t& a, uint32_t& b, uint32_t& c, uint32_t& d, const uint32_t* M) + { + a = b + rotate_left(a + (b ^ c ^ d) + md5_constants::K[round] + M[(3 * round + 5) % 16], + md5_constants::S[round]); + } + + static inline void roundi(int round, uint32_t& a, uint32_t& b, uint32_t& c, uint32_t& d, const uint32_t* M) + { + a = b + rotate_left(a + (c ^ (b | ~d)) + md5_constants::K[round] + M[(7 * round) % 16], + md5_constants::S[round]); + } + +} + +class md5_provider +{ +public: + static const bool is_xof = false; + + md5_provider() + { + } + + ~md5_provider() + { + clear(); + } + + inline void init() + { + H[0] = 0x67452301; + H[1] = 0xefcdab89; + H[2] = 0x98badcfe; + H[3] = 0x10325476; + pos = 0; + total = 0; + } + + inline void update(const unsigned char* data, size_t len) + { + detail::absorb_bytes(data, len, 64, 64, m.data(), pos, total, + [this](const unsigned char* data, size_t len) { transform(data, len); }); + } + + inline void final(unsigned char* hash) + { + total += pos * 8; + m[pos++] = 0x80; + if (pos > 56) + { + if (pos != 64) + memset(&m[pos], 0, 64 - pos); + transform(&m[0], 1); + pos = 0; + } + memset(&m[0] + pos, 0, 56 - pos); + memcpy(&m[0] + (64 - 8), &total, 64 / 8); + transform(&m[0], 1); + memcpy(hash, H.data(), 16); + } + + inline void clear() + { + zero_memory(H); + zero_memory(m); + } + + inline size_t hash_size() const { return 128; } + +private: + inline void transform(const unsigned char* data, size_t num_blks) + { + const uint32_t* M = reinterpret_cast(data); + for (uint64_t blk = 0; blk < num_blks; blk++, M += 16) + { + uint32_t a = H[0]; + uint32_t b = H[1]; + uint32_t c = H[2]; + uint32_t d = H[3]; + + md5_functions::roundf(0, a, b, c, d, M); + md5_functions::roundf(1, d, a, b, c, M); + md5_functions::roundf(2, c, d, a, b, M); + md5_functions::roundf(3, b, c, d, a, M); + md5_functions::roundf(4, a, b, c, d, M); + md5_functions::roundf(5, d, a, b, c, M); + md5_functions::roundf(6, c, d, a, b, M); + md5_functions::roundf(7, b, c, d, a, M); + md5_functions::roundf(8, a, b, c, d, M); + md5_functions::roundf(9, d, a, b, c, M); + md5_functions::roundf(10, c, d, a, b, M); + md5_functions::roundf(11, b, c, d, a, M); + md5_functions::roundf(12, a, b, c, d, M); + md5_functions::roundf(13, d, a, b, c, M); + md5_functions::roundf(14, c, d, a, b, M); + md5_functions::roundf(15, b, c, d, a, M); + + md5_functions::roundg(16, a, b, c, d, M); + md5_functions::roundg(17, d, a, b, c, M); + md5_functions::roundg(18, c, d, a, b, M); + md5_functions::roundg(19, b, c, d, a, M); + md5_functions::roundg(20, a, b, c, d, M); + md5_functions::roundg(21, d, a, b, c, M); + md5_functions::roundg(22, c, d, a, b, M); + md5_functions::roundg(23, b, c, d, a, M); + md5_functions::roundg(24, a, b, c, d, M); + md5_functions::roundg(25, d, a, b, c, M); + md5_functions::roundg(26, c, d, a, b, M); + md5_functions::roundg(27, b, c, d, a, M); + md5_functions::roundg(28, a, b, c, d, M); + md5_functions::roundg(29, d, a, b, c, M); + md5_functions::roundg(30, c, d, a, b, M); + md5_functions::roundg(31, b, c, d, a, M); + + md5_functions::roundh(32, a, b, c, d, M); + md5_functions::roundh(33, d, a, b, c, M); + md5_functions::roundh(34, c, d, a, b, M); + md5_functions::roundh(35, b, c, d, a, M); + md5_functions::roundh(36, a, b, c, d, M); + md5_functions::roundh(37, d, a, b, c, M); + md5_functions::roundh(38, c, d, a, b, M); + md5_functions::roundh(39, b, c, d, a, M); + md5_functions::roundh(40, a, b, c, d, M); + md5_functions::roundh(41, d, a, b, c, M); + md5_functions::roundh(42, c, d, a, b, M); + md5_functions::roundh(43, b, c, d, a, M); + md5_functions::roundh(44, a, b, c, d, M); + md5_functions::roundh(45, d, a, b, c, M); + md5_functions::roundh(46, c, d, a, b, M); + md5_functions::roundh(47, b, c, d, a, M); + + md5_functions::roundi(48, a, b, c, d, M); + md5_functions::roundi(49, d, a, b, c, M); + md5_functions::roundi(50, c, d, a, b, M); + md5_functions::roundi(51, b, c, d, a, M); + md5_functions::roundi(52, a, b, c, d, M); + md5_functions::roundi(53, d, a, b, c, M); + md5_functions::roundi(54, c, d, a, b, M); + md5_functions::roundi(55, b, c, d, a, M); + md5_functions::roundi(56, a, b, c, d, M); + md5_functions::roundi(57, d, a, b, c, M); + md5_functions::roundi(58, c, d, a, b, M); + md5_functions::roundi(59, b, c, d, a, M); + md5_functions::roundi(60, a, b, c, d, M); + md5_functions::roundi(61, d, a, b, c, M); + md5_functions::roundi(62, c, d, a, b, M); + md5_functions::roundi(63, b, c, d, a, M); + + H[0] += a; + H[1] += b; + H[2] += c; + H[3] += d; + } + } + + std::array H; + std::array m; + size_t pos; + uint64_t total; +}; + +} // namespace detail + +} // namespace digestpp + +#endif \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/detail/sha1_provider.hpp b/ext/include/digestpp/algorithm/detail/sha1_provider.hpp new file mode 100644 index 0000000..a5bb248 --- /dev/null +++ b/ext/include/digestpp/algorithm/detail/sha1_provider.hpp @@ -0,0 +1,162 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_PROVIDERS_SHA1_HPP +#define DIGESTPP_PROVIDERS_SHA1_HPP + +#include "../../detail/functions.hpp" +#include "../../detail/absorb_data.hpp" +#include "constants/sha1_constants.hpp" +#include + +namespace digestpp +{ + +namespace detail +{ + +namespace sha1_functions +{ + static inline uint32_t Ch(uint32_t x, uint32_t y, uint32_t z) + { + return (x & y) ^ (~x & z); + } + + static inline uint32_t Parity(uint32_t x, uint32_t y, uint32_t z) + { + return x ^ y ^ z; + } + + static inline uint32_t Maj(uint32_t x, uint32_t y, uint32_t z) + { + return (x & y) ^ (x & z) ^ (y & z); + } +} + +class sha1_provider +{ +public: + static const bool is_xof = false; + + sha1_provider() + { + } + + ~sha1_provider() + { + clear(); + } + + inline void init() + { + H[0] = 0x67452301; + H[1] = 0xefcdab89; + H[2] = 0x98badcfe; + H[3] = 0x10325476; + H[4] = 0xc3d2e1f0; + pos = 0; + total = 0; + } + + inline void update(const unsigned char* data, size_t len) + { + detail::absorb_bytes(data, len, 64, 64, m.data(), pos, total, + [this](const unsigned char* data, size_t len) { transform(data, len); }); + } + + inline void final(unsigned char* hash) + { + total += pos * 8; + m[pos++] = 0x80; + if (pos > 56) { + if (pos != 64) + memset(&m[pos], 0, 64 - pos); + transform(&m[0], 1); + pos = 0; + } + memset(&m[0] + pos, 0, 56 - pos); + uint64_t mlen = byteswap(total); + memcpy(&m[0] + (64 - 8), &mlen, 64 / 8); + transform(&m[0], 1); + for (int i = 0; i < 5; i++) + H[i] = byteswap(H[i]); + memcpy(hash, H.data(), 160/8); + } + + inline void clear() + { + zero_memory(H); + zero_memory(m); + } + + inline size_t hash_size() const { return 160; } + +private: + inline void transform(const unsigned char* data, size_t num_blks) + { + for (uint64_t blk = 0; blk < num_blks; blk++) + { + uint32_t M[16]; + for (uint32_t i = 0; i < 64 / 4; i++) + M[i] = byteswap((reinterpret_cast(data)[blk * 16 + i])); + + uint32_t W[80]; + for (int t = 0; t <= 15; t++) + W[t] = M[t]; + for (int t = 16; t <= 79; t++) + W[t] = rotate_left(W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16], 1); + + uint32_t a = H[0]; + uint32_t b = H[1]; + uint32_t c = H[2]; + uint32_t d = H[3]; + uint32_t e = H[4]; + + uint32_t K = sha1_constants::K[0]; + auto f = sha1_functions::Ch; + for (int t = 0; t <= 79; t++) + { + uint32_t T = rotate_left(a, 5) + f(b, c, d) + e + K + W[t]; + e = d; + d = c; + c = rotate_left(b, 30); + b = a; + a = T; + + if (t == 19) + { + f = sha1_functions::Parity; + K = sha1_constants::K[1]; + } + else if (t == 39) + { + f = sha1_functions::Maj; + K = sha1_constants::K[2]; + } + else if (t == 59) + { + f = sha1_functions::Parity; + K = sha1_constants::K[3]; + } + + } + H[0] += a; + H[1] += b; + H[2] += c; + H[3] += d; + H[4] += e; + } + } + + std::array H; + std::array m; + size_t pos; + uint64_t total; +}; + +} // namespace detail + +} // namespace digestpp + +#endif \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/detail/sha2_provider.hpp b/ext/include/digestpp/algorithm/detail/sha2_provider.hpp new file mode 100644 index 0000000..e47008a --- /dev/null +++ b/ext/include/digestpp/algorithm/detail/sha2_provider.hpp @@ -0,0 +1,318 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_PROVIDERS_SHA2_HPP +#define DIGESTPP_PROVIDERS_SHA2_HPP + +#include "../../detail/functions.hpp" +#include "../../detail/absorb_data.hpp" +#include "../../detail/validate_hash_size.hpp" +#include "constants/sha2_constants.hpp" +#include + +namespace digestpp +{ + +namespace detail +{ + +namespace sha2_functions +{ + template + static inline T Ch(T x, T y, T z) + { + return (x & y) ^ (~x & z); + } + + template + static inline T Maj(T x, T y, T z) + { + return (x & y) ^ (x & z) ^ (y & z); + } + + static inline uint64_t sum0(uint64_t x) + { + return rotate_right(x, 28) ^ rotate_right(x, 34) ^ rotate_right(x, 39); + } + + static inline uint64_t sum1(uint64_t x) + { + return rotate_right(x, 14) ^ rotate_right(x, 18) ^ rotate_right(x, 41); + } + + static inline uint64_t sigma0(uint64_t x) + { + return rotate_right(x, 1) ^ rotate_right(x, 8) ^ (x >> 7); + } + + static inline uint64_t sigma1(uint64_t x) + { + return rotate_right(x, 19) ^ rotate_right(x, 61) ^ (x >> 6); + } + + static inline uint32_t sum0(uint32_t x) + { + return rotate_right(x, 2) ^ rotate_right(x, 13) ^ rotate_right(x, 22); + } + + static inline uint32_t sum1(uint32_t x) + { + return rotate_right(x, 6) ^ rotate_right(x, 11) ^ rotate_right(x, 25); + } + + static inline uint32_t sigma0(uint32_t x) + { + return rotate_right(x, 7) ^ rotate_right(x, 18) ^ (x >> 3); + } + + static inline uint32_t sigma1(uint32_t x) + { + return rotate_right(x, 17) ^ rotate_right(x, 19) ^ (x >> 10); + } +} + +// SHA-224, SHA-256, SHA-384, SHA-512/t algorithm +// SHA-512/t supports any output size up to 512 bits; in this case O must be 0 and output size provided to the constructor +template +class sha2_provider +{ +public: + static const bool is_xof = false; + + template::type* = nullptr> + sha2_provider() + : hs(O) + { + } + + template::type* = nullptr> + sha2_provider(size_t hashsize = N) + : hs(hashsize) + { + detail::validate_hash_size(hashsize, N); + } + + ~sha2_provider() + { + clear(); + } + + inline void init() + { + pos = 0; + total = 0; + + // precalculated initial values for most common output sizes + switch(hs) + { + case 224: + H[0] = 0x8C3D37C819544DA2ull; + H[1] = 0x73E1996689DCD4D6ull; + H[2] = 0x1DFAB7AE32FF9C82ull; + H[3] = 0x679DD514582F9FCFull; + H[4] = 0x0F6D2B697BD44DA8ull; + H[5] = 0x77E36F7304C48942ull; + H[6] = 0x3F9D85A86A1D36C8ull; + H[7] = 0x1112E6AD91D692A1ull; + return; + case 256: + H[0] = 0x22312194FC2BF72Cull; + H[1] = 0x9F555FA3C84C64C2ull; + H[2] = 0x2393B86B6F53B151ull; + H[3] = 0x963877195940EABDull; + H[4] = 0x96283EE2A88EFFE3ull; + H[5] = 0xBE5E1E2553863992ull; + H[6] = 0x2B0199FC2C85B8AAull; + H[7] = 0x0EB72DDC81C52CA2ull; + return; + case 384: + H[0] = 0xcbbb9d5dc1059ed8ull; + H[1] = 0x629a292a367cd507ull; + H[2] = 0x9159015a3070dd17ull; + H[3] = 0x152fecd8f70e5939ull; + H[4] = 0x67332667ffc00b31ull; + H[5] = 0x8eb44a8768581511ull; + H[6] = 0xdb0c2e0d64f98fa7ull; + H[7] = 0x47b5481dbefa4fa4ull; + return; + default: + H[0] = 0x6a09e667f3bcc908ull; + H[1] = 0xbb67ae8584caa73bull; + H[2] = 0x3c6ef372fe94f82bull; + H[3] = 0xa54ff53a5f1d36f1ull; + H[4] = 0x510e527fade682d1ull; + H[5] = 0x9b05688c2b3e6c1full; + H[6] = 0x1f83d9abfb41bd6bull; + H[7] = 0x5be0cd19137e2179ull; + } + if (hs == 512) + return; + + // calculate initial values for SHA-512/t with a different output size + for (int i = 0; i < 8; i++) + H[i] ^= 0xa5a5a5a5a5a5a5a5ull; + std::string tmp = "SHA-512/" + std::to_string(hs); + + update(reinterpret_cast(&tmp[0]), tmp.length()); + unsigned char buf[512 / 8]; + final(buf); + for (int i = 0; i < 8; i++) + H[i] = byteswap(H[i]); + pos = 0; + total = 0; + } + + inline void update(const unsigned char* data, size_t len) + { + detail::absorb_bytes(data, len, N / 4, N / 4, m.data(), pos, total, + [this](const unsigned char* data, size_t len) { transform(data, len); }); + } + + inline void final(unsigned char* hash) + { + total += pos * 8; + m[pos++] = 0x80; + if (pos > N / 4 - sizeof(T) * 2) { + if (pos != N / 4) + memset(&m[pos], 0, N / 4 - pos); + transform(m.data(), 1); + pos = 0; + } + memset(&m[pos], 0, N / 4 - pos); + uint64_t mlen = byteswap(total); + memcpy(&m[N / 4 - 8], &mlen, 64 / 8); + transform(m.data(), 1); + for (int i = 0; i < 8; i++) + H[i] = byteswap(H[i]); + memcpy(hash, &H[0], hs/8); + } + + inline void clear() + { + zero_memory(H); + zero_memory(m); + } + + inline size_t hash_size() const { return hs; } + + inline T getK(int t) const; + +private: + inline void transform(const unsigned char* data, size_t num_blks) + { + for (size_t blk = 0; blk < num_blks; blk++) + { + T M[16]; + for (int i = 0; i < 16; i++) + M[i] = byteswap(reinterpret_cast(data)[blk * 16 + i]); + + const int rounds = N == 512 ? 80 : 64; + T W[rounds]; + for (int t = 0; t <= 15; t++) + W[t] = M[t]; + for (int t = 16; t < rounds; t++) + W[t] = sha2_functions::sigma1(W[t - 2]) + W[t - 7] + sha2_functions::sigma0(W[t - 15]) + W[t - 16]; + + T a = H[0]; + T b = H[1]; + T c = H[2]; + T d = H[3]; + T e = H[4]; + T f = H[5]; + T g = H[6]; + T h = H[7]; + + for (int t = 0; t < rounds; t++) + { + T T1 = h + sha2_functions::sum1(e) + sha2_functions::Ch(e, f, g) + getK(t) + W[t]; + T T2 = sha2_functions::sum0(a) + sha2_functions::Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + } + H[0] += a; + H[1] += b; + H[2] += c; + H[3] += d; + H[4] += e; + H[5] += f; + H[6] += g; + H[7] += h; + } + + } + + constexpr static size_t N = sizeof(T) == 8 ? 512 : 256; + std::array H; + std::array m; + size_t pos; + uint64_t total; + size_t hs; +}; + +template<> +inline uint32_t sha2_provider::getK(int t) const +{ + return sha256_constants::K[t]; +} + +template<> +inline uint32_t sha2_provider::getK(int t) const +{ + return sha256_constants::K[t]; +} + +template<> +inline uint64_t sha2_provider::getK(int t) const +{ + return sha512_constants::K[t]; +} + +template<> +inline uint64_t sha2_provider::getK(int t) const +{ + return sha512_constants::K[t]; +} + +template<> +inline void sha2_provider::init() +{ + pos = 0; + total = 0; + H[0] = 0xc1059ed8; + H[1] = 0x367cd507; + H[2] = 0x3070dd17; + H[3] = 0xf70e5939; + H[4] = 0xffc00b31; + H[5] = 0x68581511; + H[6] = 0x64f98fa7; + H[7] = 0xbefa4fa4; +} + +template<> +inline void sha2_provider::init() +{ + pos = 0; + total = 0; + H[0] = 0x6a09e667; + H[1] = 0xbb67ae85; + H[2] = 0x3c6ef372; + H[3] = 0xa54ff53a; + H[4] = 0x510e527f; + H[5] = 0x9b05688c; + H[6] = 0x1f83d9ab; + H[7] = 0x5be0cd19; +} + +} // namespace detail + +} // namespace digestpp + +#endif \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/detail/sha3_provider.hpp b/ext/include/digestpp/algorithm/detail/sha3_provider.hpp new file mode 100644 index 0000000..b09126b --- /dev/null +++ b/ext/include/digestpp/algorithm/detail/sha3_provider.hpp @@ -0,0 +1,186 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_PROVIDERS_SHA3_HPP +#define DIGESTPP_PROVIDERS_SHA3_HPP + +#include "../../detail/functions.hpp" +#include "../../detail/absorb_data.hpp" +#include "../../detail/validate_hash_size.hpp" +#include "constants/sha3_constants.hpp" +#include + +namespace digestpp +{ + +namespace detail +{ + +namespace sha3_functions +{ + template + static inline void transform(uint64_t* A) + { + for (int round = 24 - R; round < 24; round++) + { + uint64_t C[5], D[5]; + C[0] = A[0 * 5 + 0] ^ A[1 * 5 + 0] ^ A[2 * 5 + 0] ^ A[3 * 5 + 0] ^ A[4 * 5 + 0]; + C[1] = A[0 * 5 + 1] ^ A[1 * 5 + 1] ^ A[2 * 5 + 1] ^ A[3 * 5 + 1] ^ A[4 * 5 + 1]; + C[2] = A[0 * 5 + 2] ^ A[1 * 5 + 2] ^ A[2 * 5 + 2] ^ A[3 * 5 + 2] ^ A[4 * 5 + 2]; + C[3] = A[0 * 5 + 3] ^ A[1 * 5 + 3] ^ A[2 * 5 + 3] ^ A[3 * 5 + 3] ^ A[4 * 5 + 3]; + C[4] = A[0 * 5 + 4] ^ A[1 * 5 + 4] ^ A[2 * 5 + 4] ^ A[3 * 5 + 4] ^ A[4 * 5 + 4]; + + D[0] = C[4] ^ rotate_left(C[1], 1); + D[1] = C[0] ^ rotate_left(C[2], 1); + D[2] = C[1] ^ rotate_left(C[3], 1); + D[3] = C[2] ^ rotate_left(C[4], 1); + D[4] = C[3] ^ rotate_left(C[0], 1); + + uint64_t B00 = A[0 * 5 + 0] ^ D[0]; + uint64_t B10 = rotate_left(A[0 * 5 + 1] ^ D[1], 1); + uint64_t B20 = rotate_left(A[0 * 5 + 2] ^ D[2], 62); + uint64_t B5 = rotate_left(A[0 * 5 + 3] ^ D[3], 28); + uint64_t B15 = rotate_left(A[0 * 5 + 4] ^ D[4], 27); + + uint64_t B16 = rotate_left(A[1 * 5 + 0] ^ D[0], 36); + uint64_t B1 = rotate_left(A[1 * 5 + 1] ^ D[1], 44); + uint64_t B11 = rotate_left(A[1 * 5 + 2] ^ D[2], 6); + uint64_t B21 = rotate_left(A[1 * 5 + 3] ^ D[3], 55); + uint64_t B6 = rotate_left(A[1 * 5 + 4] ^ D[4], 20); + + uint64_t B7 = rotate_left(A[2 * 5 + 0] ^ D[0], 3); + uint64_t B17 = rotate_left(A[2 * 5 + 1] ^ D[1], 10); + uint64_t B2 = rotate_left(A[2 * 5 + 2] ^ D[2], 43); + uint64_t B12 = rotate_left(A[2 * 5 + 3] ^ D[3], 25); + uint64_t B22 = rotate_left(A[2 * 5 + 4] ^ D[4], 39); + + uint64_t B23 = rotate_left(A[3 * 5 + 0] ^ D[0], 41); + uint64_t B8 = rotate_left(A[3 * 5 + 1] ^ D[1], 45); + uint64_t B18 = rotate_left(A[3 * 5 + 2] ^ D[2], 15); + uint64_t B3 = rotate_left(A[3 * 5 + 3] ^ D[3], 21); + uint64_t B13 = rotate_left(A[3 * 5 + 4] ^ D[4], 8); + + uint64_t B14 = rotate_left(A[4 * 5 + 0] ^ D[0], 18); + uint64_t B24 = rotate_left(A[4 * 5 + 1] ^ D[1], 2); + uint64_t B9 = rotate_left(A[4 * 5 + 2] ^ D[2], 61); + uint64_t B19 = rotate_left(A[4 * 5 + 3] ^ D[3], 56); + uint64_t B4 = rotate_left(A[4 * 5 + 4] ^ D[4], 14); + + A[0 * 5 + 0] = B00 ^ ((~B1) & B2); + A[0 * 5 + 1] = B1 ^ ((~B2) & B3); + A[0 * 5 + 2] = B2 ^ ((~B3) & B4); + A[0 * 5 + 3] = B3 ^ ((~B4) & B00); + A[0 * 5 + 4] = B4 ^ ((~B00) & B1); + + A[1 * 5 + 0] = B5 ^ ((~B6) & B7); + A[1 * 5 + 1] = B6 ^ ((~B7) & B8); + A[1 * 5 + 2] = B7 ^ ((~B8) & B9); + A[1 * 5 + 3] = B8 ^ ((~B9) & B5); + A[1 * 5 + 4] = B9 ^ ((~B5) & B6); + + A[2 * 5 + 0] = B10 ^ ((~B11) & B12); + A[2 * 5 + 1] = B11 ^ ((~B12) & B13); + A[2 * 5 + 2] = B12 ^ ((~B13) & B14); + A[2 * 5 + 3] = B13 ^ ((~B14) & B10); + A[2 * 5 + 4] = B14 ^ ((~B10) & B11); + + A[3 * 5 + 0] = B15 ^ ((~B16) & B17); + A[3 * 5 + 1] = B16 ^ ((~B17) & B18); + A[3 * 5 + 2] = B17 ^ ((~B18) & B19); + A[3 * 5 + 3] = B18 ^ ((~B19) & B15); + A[3 * 5 + 4] = B19 ^ ((~B15) & B16); + + A[4 * 5 + 0] = B20 ^ ((~B21) & B22); + A[4 * 5 + 1] = B21 ^ ((~B22) & B23); + A[4 * 5 + 2] = B22 ^ ((~B23) & B24); + A[4 * 5 + 3] = B23 ^ ((~B24) & B20); + A[4 * 5 + 4] = B24 ^ ((~B20) & B21); + + A[0] ^= sha3_constants::RC[round]; + } + } + + template + static inline void transform(const unsigned char* data, uint64_t num_blks, uint64_t* A, size_t rate) + { + size_t r = rate / 8; + size_t r64 = rate / 64; + for (uint64_t blk = 0; blk < num_blks; blk++) + { + for (size_t i = 0; i < r64; i++) + A[i] ^= reinterpret_cast(data+blk*r)[i]; + + transform(A); + } + } + +} // namespace sha3_functions + + +class sha3_provider +{ +public: + static const bool is_xof = false; + + sha3_provider(size_t hashsize) + : hs(hashsize) + { + validate_hash_size(hashsize, {224, 256, 384, 512}); + rate = 1600U - hs * 2; + } + + ~sha3_provider() + { + clear(); + } + + inline void init() + { + zero_memory(A); + pos = 0; + total = 0; + } + + inline void update(const unsigned char* data, size_t len) + { + detail::absorb_bytes(data, len, rate / 8, rate / 8, m.data(), pos, total, + [this](const unsigned char* data, size_t len) { sha3_functions::transform<24>(data, len, A.data(), rate); }); + } + + inline void final(unsigned char* hash) + { + size_t r = rate / 8; + m[pos++] = 0x06; + if (r != pos) + memset(&m[pos], 0, r - pos); + m[r - 1] |= 0x80; + sha3_functions::transform<24>(m.data(), 1, A.data(), rate); + memcpy(hash, A.data(), hash_size() / 8); + } + + inline size_t hash_size() const + { + return hs; + } + + inline void clear() + { + zero_memory(A); + zero_memory(m); + } + +private: + std::array A; + std::array m; + size_t pos; + size_t hs; + size_t rate; + uint64_t total; +}; + +} // namespace detail + +} // namespace digestpp + +#endif // DIGESTPP_PROVIDERS_SHA3_HPP diff --git a/ext/include/digestpp/algorithm/detail/shake_provider.hpp b/ext/include/digestpp/algorithm/detail/shake_provider.hpp new file mode 100644 index 0000000..a43f3cc --- /dev/null +++ b/ext/include/digestpp/algorithm/detail/shake_provider.hpp @@ -0,0 +1,184 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_PROVIDERS_SHAKE_HPP +#define DIGESTPP_PROVIDERS_SHAKE_HPP + +#include "../../detail/functions.hpp" +#include "../../detail/absorb_data.hpp" +#include "sha3_provider.hpp" +#include + +namespace digestpp +{ + +namespace detail +{ + +namespace shake_functions +{ + static inline size_t left_encode(size_t num, unsigned char* buf) + { + // first, calculate length + unsigned char n = 1; + size_t tmp = num; + while (tmp >>= 8) + ++n; + buf[0] = n; + size_t result = n + 1; + size_t i = 0; + while (n) + buf[n--] = static_cast(num >> (8*i++)); + return result; + } + + static inline size_t right_encode(size_t num, unsigned char* buf, bool k12) + { + // first, calculate length + unsigned char n = k12 ? num ? 1 : 0 : 1; + size_t tmp = num; + while (tmp >>= 8) + ++n; + buf[n] = n; + size_t result = n + 1; + size_t i = 0; + while (n--) + buf[n] = static_cast(num >> (8*i++)); + return result; + } + +} // namespace shake_functions + + +template +class shake_provider +{ +public: + static const bool is_xof = true; + + shake_provider() + { + static_assert(B == 128 || B == 256, "SHAKE only supports 128 and 256 bits"); + } + + ~shake_provider() + { + clear(); + } + + inline void set_function_name(const std::string& function_name) + { + N = function_name; + } + + inline void set_customization(const std::string& customization) + { + S = customization; + } + + inline void init() + { + zero_memory(A); + pos = 0; + total = 0; + squeezing = false; + suffix = 0; + + if (!N.empty() || !S.empty()) + { + unsigned char buf[1024]; + size_t r = rate / 8; + size_t len = shake_functions::left_encode(r, buf); + size_t total = len; + update(buf, len); + len = shake_functions::left_encode(N.length() * 8, buf); + total += len; + update(buf, len); + if (!N.empty()) + update(reinterpret_cast(N.data()), N.length()); + len = shake_functions::left_encode(S.length() * 8, buf); + update(buf, len); + total += len; + if (!S.empty()) + update(reinterpret_cast(S.data()), S.length()); + total += S.length() + N.length(); + + len = r - (total % r); + memset(buf, 0, len); + update(buf, len); + } + } + + inline void update(const unsigned char* data, size_t len) + { + detail::absorb_bytes(data, len, rate / 8, rate / 8, m.data(), pos, total, + [this](const unsigned char* data, size_t len) { sha3_functions::transform(data, len, A.data(), rate); }); + } + + inline void set_suffix(unsigned char s) + { + suffix = s; + } + + inline void squeeze(unsigned char* hash, size_t hs) + { + size_t r = rate / 8; + size_t processed = 0; + if (!squeezing) + { + m[pos++] = suffix ? suffix : N.empty() && S.empty() ? 0x1F : 0x04; + if (r != pos) + memset(&m[pos], 0, r - pos); + m[r - 1] |= 0x80; + sha3_functions::transform(m.data(), 1, A.data(), rate); + squeezing = true; + } + else if (pos < r) + { + size_t to_copy = std::min(hs, r - pos); + memcpy(hash, reinterpret_cast(A.data()) + pos, to_copy); + processed += to_copy; + pos += to_copy; + } + else if (pos == r) + { + sha3_functions::transform(A.data()); + } + while (processed < hs) + { + if (processed) + sha3_functions::transform(A.data()); + pos = std::min(hs - processed, r); + memcpy(hash + processed, A.data(), pos); + processed += pos; + } + } + + inline void clear() + { + zero_memory(A); + zero_memory(m); + zero_memory(N); + zero_memory(S); + N.clear(); + S.clear(); + } + +private: + std::array A; + std::array m; + std::string N; + std::string S; + const size_t rate = B == 128 ? 1344 : 1088; + size_t pos; + size_t total; + bool squeezing; + unsigned char suffix; +}; + +} // namespace detail + +} // namespace digestpp + +#endif // DIGESTPP_PROVIDERS_SHAKE_HPP diff --git a/ext/include/digestpp/algorithm/detail/skein_provider.hpp b/ext/include/digestpp/algorithm/detail/skein_provider.hpp new file mode 100644 index 0000000..bfb1dfb --- /dev/null +++ b/ext/include/digestpp/algorithm/detail/skein_provider.hpp @@ -0,0 +1,387 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_PROVIDERS_SKEIN_HPP +#define DIGESTPP_PROVIDERS_SKEIN_HPP + +#include "../../detail/functions.hpp" +#include "../../detail/absorb_data.hpp" +#include "../../detail/validate_hash_size.hpp" +#include "constants/skein_constants.hpp" +#include + +namespace digestpp +{ + +namespace detail +{ + +template +struct skein_functions +{ +}; + +template<> +struct skein_functions<4> +{ + template static inline void GTv4(uint64_t* G) + { + G[skein_constants::I4[r][0]] += G[skein_constants::I4[r][1]]; + G[skein_constants::I4[r][1]] = rotate_left(G[skein_constants::I4[r][1]], + skein_constants::C4[r][0]) ^ G[skein_constants::I4[r][0]]; + G[skein_constants::I4[r][2]] += G[skein_constants::I4[r][3]]; + G[skein_constants::I4[r][3]] = rotate_left(G[skein_constants::I4[r][3]], + skein_constants::C4[r][1]) ^ G[skein_constants::I4[r][2]]; + } + + template + static inline void KStRv4(uint64_t* G, uint64_t* keys, uint64_t* tweaks) + { + G[0] += keys[(r + 0 + 1) % 5]; + G[1] += keys[(r + 1 + 1) % 5] + tweaks[(r + 1) % 3]; + G[2] += keys[(r + 2 + 1) % 5] + tweaks[(r + 2) % 3]; + G[3] += keys[(r + 3 + 1) % 5] + r + 1; + } + + template + static inline void G8(uint64_t* G, uint64_t* keys, uint64_t* tweaks) + { + GTv4<0>(G); + GTv4<1>(G); + GTv4<2>(G); + GTv4<3>(G); + KStRv4(G, keys, tweaks); + GTv4<4>(G); + GTv4<5>(G); + GTv4<6>(G); + GTv4<7>(G); + KStRv4(G, keys, tweaks); + } +}; + +template<> +struct skein_functions<8> +{ + template static inline void GTv4(uint64_t* G) + { + G[skein_constants::I8[r][0]] += G[skein_constants::I8[r][1]]; + G[skein_constants::I8[r][1]] = rotate_left(G[skein_constants::I8[r][1]], + skein_constants::C8[r][0]) ^ G[skein_constants::I8[r][0]]; + G[skein_constants::I8[r][2]] += G[skein_constants::I8[r][3]]; + G[skein_constants::I8[r][3]] = rotate_left(G[skein_constants::I8[r][3]], + skein_constants::C8[r][1]) ^ G[skein_constants::I8[r][2]]; + G[skein_constants::I8[r][4]] += G[skein_constants::I8[r][5]]; + G[skein_constants::I8[r][5]] = rotate_left(G[skein_constants::I8[r][5]], + skein_constants::C8[r][2]) ^ G[skein_constants::I8[r][4]]; + G[skein_constants::I8[r][6]] += G[skein_constants::I8[r][7]]; + G[skein_constants::I8[r][7]] = rotate_left(G[skein_constants::I8[r][7]], + skein_constants::C8[r][3]) ^ G[skein_constants::I8[r][6]]; + } + + template + static inline void KStRv4(uint64_t* G, uint64_t* keys, uint64_t* tweaks) + { + G[0] += keys[(r + 0 + 1) % 9]; + G[1] += keys[(r + 1 + 1) % 9]; + G[2] += keys[(r + 2 + 1) % 9]; + G[3] += keys[(r + 3 + 1) % 9]; + G[4] += keys[(r + 4 + 1) % 9]; + G[5] += keys[(r + 5 + 1) % 9] + tweaks[(r + 1) % 3]; + G[6] += keys[(r + 6 + 1) % 9] + tweaks[(r + 2) % 3]; + G[7] += keys[(r + 7 + 1) % 9] + r + 1; + } + + template + static inline void G8(uint64_t* G, uint64_t* keys, uint64_t* tweaks) + { + GTv4<0>(G); + GTv4<1>(G); + GTv4<2>(G); + GTv4<3>(G); + KStRv4(G, keys, tweaks); + GTv4<4>(G); + GTv4<5>(G); + GTv4<6>(G); + GTv4<7>(G); + KStRv4(G, keys, tweaks); + } +}; + +template<> +struct skein_functions<16> +{ + + template static inline void GTv4(uint64_t* G) + { + G[skein_constants::I16[r][0]] += G[skein_constants::I16[r][1]]; + G[skein_constants::I16[r][1]] = rotate_left(G[skein_constants::I16[r][1]], + skein_constants::C16[r][0]) ^ G[skein_constants::I16[r][0]]; + G[skein_constants::I16[r][2]] += G[skein_constants::I16[r][3]]; + G[skein_constants::I16[r][3]] = rotate_left(G[skein_constants::I16[r][3]], + skein_constants::C16[r][1]) ^ G[skein_constants::I16[r][2]]; + G[skein_constants::I16[r][4]] += G[skein_constants::I16[r][5]]; + G[skein_constants::I16[r][5]] = rotate_left(G[skein_constants::I16[r][5]], + skein_constants::C16[r][2]) ^ G[skein_constants::I16[r][4]]; + G[skein_constants::I16[r][6]] += G[skein_constants::I16[r][7]]; + G[skein_constants::I16[r][7]] = rotate_left(G[skein_constants::I16[r][7]], + skein_constants::C16[r][3]) ^ G[skein_constants::I16[r][6]]; + G[skein_constants::I16[r][8]] += G[skein_constants::I16[r][9]]; + G[skein_constants::I16[r][9]] = rotate_left(G[skein_constants::I16[r][9]], + skein_constants::C16[r][4]) ^ G[skein_constants::I16[r][8]]; + G[skein_constants::I16[r][10]] += G[skein_constants::I16[r][11]]; + G[skein_constants::I16[r][11]] = rotate_left(G[skein_constants::I16[r][11]], + skein_constants::C16[r][5]) ^ G[skein_constants::I16[r][10]]; + G[skein_constants::I16[r][12]] += G[skein_constants::I16[r][13]]; + G[skein_constants::I16[r][13]] = rotate_left(G[skein_constants::I16[r][13]], + skein_constants::C16[r][6]) ^ G[skein_constants::I16[r][12]]; + G[skein_constants::I16[r][14]] += G[skein_constants::I16[r][15]]; + G[skein_constants::I16[r][15]] = rotate_left(G[skein_constants::I16[r][15]], + skein_constants::C16[r][7]) ^ G[skein_constants::I16[r][14]]; + } + + template + static inline void KStRv4(uint64_t* G, uint64_t* keys, uint64_t* tweaks) + { + G[0] += keys[(r + 0 + 1) % 17]; + G[1] += keys[(r + 1 + 1) % 17]; + G[2] += keys[(r + 2 + 1) % 17]; + G[3] += keys[(r + 3 + 1) % 17]; + G[4] += keys[(r + 4 + 1) % 17]; + G[5] += keys[(r + 5 + 1) % 17]; + G[6] += keys[(r + 6 + 1) % 17]; + G[7] += keys[(r + 7 + 1) % 17]; + G[8] += keys[(r + 8 + 1) % 17]; + G[9] += keys[(r + 9 + 1) % 17]; + G[10] += keys[(r + 10 + 1) % 17]; + G[11] += keys[(r + 11 + 1) % 17]; + G[12] += keys[(r + 12 + 1) % 17]; + G[13] += keys[(r + 13 + 1) % 17] + tweaks[(r + 1) % 3]; + G[14] += keys[(r + 14 + 1) % 17] + tweaks[(r + 2) % 3]; + G[15] += keys[(r + 15 + 1) % 17] + r + 1; + } + + template + static inline void G8(uint64_t* G, uint64_t* keys, uint64_t* tweaks) + { + GTv4<0>(G); + GTv4<1>(G); + GTv4<2>(G); + GTv4<3>(G); + KStRv4(G, keys, tweaks); + GTv4<4>(G); + GTv4<5>(G); + GTv4<6>(G); + GTv4<7>(G); + KStRv4(G, keys, tweaks); + } +}; + +template +class skein_provider +{ +public: + static const bool is_xof = XOF; + + skein_provider(size_t hashsize = N) + : hs(hashsize) + { + validate_hash_size(hashsize, SIZE_MAX); + } + + ~skein_provider() + { + clear(); + } + + inline void set_personalization(const std::string& personalization) + { + p = personalization; + } + + inline void set_nonce(const std::string& nonce) + { + n = nonce; + } + + inline void set_key(const std::string& key) + { + k = key; + } + + inline void init() + { + squeezing = false; + tweak[0] = 0ULL; + pos = 0; + total = 0; + zero_memory(H); + inject_parameter(k, 0ULL); + tweak[1] = (1ULL << 62) | (4ULL << 56) | (1ULL << 63); + zero_memory(m); + m[0] = 0x53; + m[1] = 0x48; + m[2] = 0x41; + m[3] = 0x33; + m[4] = 0x01; + uint64_t size64 = XOF ? static_cast(-1) : hs; + memcpy(&m[8], &size64, 8); + transform(m.data(), 1, 32); + pos = 0; + total = 0; + tweak[0] = 0ULL; + tweak[1] = (1ULL << 62) | (48ULL << 56); + inject_parameter(p, 8ULL); + inject_parameter(n, 20ULL); + + } + + inline void update(const unsigned char* data, size_t len) + { + detail::absorb_bytes(data, len, N / 8, N / 8 + 1, m.data(), pos, total, + [this](const unsigned char* data, size_t len) { transform(data, len, N / 8); }); + } + + inline void squeeze(unsigned char* hash, size_t hs) + { + size_t processed = 0; + if (!squeezing) + { + squeezing = true; + tweak[1] |= 1ull << 63; // last block + if (pos < N / 8) + memset(&m[pos], 0, N / 8 - pos); + + transform(m.data(), 1, pos); + memset(&m[0], 0, N / 8); + memcpy(&hbk[0], H.data(), N / 8); + pos = 0; + total = 0; + } + else if (pos < N / 8) + { + size_t to_copy = std::min(hs, N / 8 - pos); + memcpy(hash, reinterpret_cast(H.data()) + pos, to_copy); + processed += to_copy; + pos += to_copy; + } + while (processed < hs) + { + pos = std::min(hs - processed, N / 8); + tweak[0] = 0; + tweak[1] = 255ULL << 56; + memcpy(&m[0], &total, 8); + memcpy(&H[0], hbk.data(), N / 8); + transform(m.data(), 1, 8); + memcpy(hash + processed, H.data(), pos); + processed += pos; + ++total; + } + } + + inline void final(unsigned char* hash) + { + return squeeze(hash, hs / 8); + } + + inline size_t hash_size() const + { + return hs; + } + + inline void clear() + { + zero_memory(H); + zero_memory(hbk); + zero_memory(m); + zero_memory(tweak); + zero_memory(p); + zero_memory(n); + zero_memory(k); + p.clear(); + n.clear(); + k.clear(); + } + +private: + inline void transform(const unsigned char* mp, uint64_t num_blks, size_t reallen) + { + uint64_t keys[N / 64 + 1]; + uint64_t tweaks[3]; + + for (uint64_t b = 0; b < num_blks; b++) + { + uint64_t M[N / 64]; + uint64_t G[N / 64]; + for (uint64_t i = 0; i < N / 64; i++) + { + M[i] = (reinterpret_cast(mp)[b * N / 64 + i]); + } + memcpy(keys, H.data(), sizeof(uint64_t) * N / 64); + memcpy(tweaks, tweak.data(), sizeof(uint64_t) * 2); + tweaks[0] += reallen; + tweaks[2] = tweaks[0] ^ tweaks[1]; + keys[N / 64] = 0x1BD11BDAA9FC1A22ULL; + for (int i = 0; i < N / 64; i++) + { + keys[N / 64] ^= keys[i]; + G[i] = M[i] + keys[i]; + } + G[N / 64 - 3] += tweaks[0]; + G[N / 64 - 2] += tweaks[1]; + + skein_functions::template G8<0>(G, keys, tweaks); + skein_functions::template G8<2>(G, keys, tweaks); + skein_functions::template G8<4>(G, keys, tweaks); + skein_functions::template G8<6>(G, keys, tweaks); + skein_functions::template G8<8>(G, keys, tweaks); + skein_functions::template G8<10>(G, keys, tweaks); + skein_functions::template G8<12>(G, keys, tweaks); + skein_functions::template G8<14>(G, keys, tweaks); + skein_functions::template G8<16>(G, keys, tweaks); + if (N == 1024) + skein_functions::template G8<18>(G, keys, tweaks); + + tweaks[1] &= ~(64ULL << 56); + tweak[0] = tweaks[0]; + tweak[1] = tweaks[1]; + + for (int i = 0; i < N / 64; i++) + H[i] = G[i] ^ M[i]; + } + } + + inline void inject_parameter(const std::string& p, uint64_t code) + { + if (p.empty()) + return; + + tweak[1] = (1ULL << 62) | (code << 56); + update(reinterpret_cast(p.data()), p.length()); + tweak[1] |= 1ull << 63; // last block + if (pos < N / 8) + memset(&m[pos], 0, N / 8 - pos); + transform(m.data(), 1, pos); + squeezing = false; + pos = 0; + total = 0; + tweak[0] = 0ULL; + tweak[1] = (1ULL << 62) | (48ULL << 56); + } + + std::array H, hbk; + std::array m; + size_t pos; + uint64_t total; + std::array tweak; + size_t hs; + bool squeezing; + std::string p, n, k; +}; + + +} // namespace detail + +} // namespace digestpp + +#endif diff --git a/ext/include/digestpp/algorithm/detail/sm3_provider.hpp b/ext/include/digestpp/algorithm/detail/sm3_provider.hpp new file mode 100644 index 0000000..9a2dcd0 --- /dev/null +++ b/ext/include/digestpp/algorithm/detail/sm3_provider.hpp @@ -0,0 +1,188 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_PROVIDERS_SM3_HPP +#define DIGESTPP_PROVIDERS_SM3_HPP + +#include "../../detail/functions.hpp" +#include "../../detail/absorb_data.hpp" +#include + +namespace digestpp +{ + +namespace detail +{ + +namespace sm3_functions +{ + static inline uint32_t xorf(uint32_t x, uint32_t y, uint32_t z) + { + return x ^ y ^ z; + } + + static inline uint32_t ff1(uint32_t x, uint32_t y, uint32_t z) + { + return (x & y) ^ (x & z) ^ (y & z); + } + + static inline uint32_t gg1(uint32_t x, uint32_t y, uint32_t z) + { + return (x & y) ^ (~x & z); + } + + static inline uint32_t p0(uint32_t x) + { + return x ^ rotate_left(x, 9) ^ rotate_left(x, 17); + } + + static inline uint32_t p1(uint32_t x) + { + return x ^ rotate_left(x, 15) ^ rotate_left(x, 23); + } +} + +class sm3_provider +{ +public: + static const bool is_xof = false; + + sm3_provider() + { + } + + ~sm3_provider() + { + clear(); + } + + inline void init() + { + H[0] = 0x7380166f; + H[1] = 0x4914b2b9; + H[2] = 0x172442d7; + H[3] = 0xda8a0600; + H[4] = 0xa96f30bc; + H[5] = 0x163138aa; + H[6] = 0xe38dee4d; + H[7] = 0xb0fb0e4e; + pos = 0; + total = 0; + } + + inline void update(const unsigned char* data, size_t len) + { + detail::absorb_bytes(data, len, 64, 64, m.data(), pos, total, + [this](const unsigned char* data, size_t len) { transform(data, len); }); + } + + inline void final(unsigned char* hash) + { + total += pos * 8; + m[pos++] = 0x80; + if (pos > 56) + { + if (pos != 64) + memset(&m[pos], 0, 64 - pos); + transform(m.data(), 1); + pos = 0; + } + memset(&m[pos], 0, 56 - pos); + uint64_t mlen = byteswap(total); + memcpy(&m[64 - 8], &mlen, 64 / 8); + transform(m.data(), 1); + for (int i = 0; i < 8; i++) + H[i] = byteswap(H[i]); + memcpy(hash, H.data(), 32); + } + + inline void clear() + { + zero_memory(H); + zero_memory(m); + } + + inline size_t hash_size() const { return 256; } + +private: + inline void transform(const unsigned char* data, size_t num_blks) + { + for (uint64_t blk = 0; blk < num_blks; blk++) + { + uint32_t M[16]; + for (uint32_t i = 0; i < 64 / 4; i++) + M[i] = byteswap(reinterpret_cast(data)[blk * 16 + i]); + + uint32_t W[68]; + uint32_t W2[64]; + for (int t = 0; t <= 15; t++) + W[t] = M[t]; + for (int t = 16; t <= 67; t++) + W[t] = sm3_functions::p1(W[t - 16] ^ W[t - 9] ^ rotate_left(W[t - 3], 15)) ^ rotate_left(W[t - 13], 7) ^ W[t - 6]; + for (int t = 0; t <= 63; t++) + W2[t] = W[t] ^ W[t + 4]; + + uint32_t a = H[0]; + uint32_t b = H[1]; + uint32_t c = H[2]; + uint32_t d = H[3]; + uint32_t e = H[4]; + uint32_t f = H[5]; + uint32_t g = H[6]; + uint32_t h = H[7]; + + for (int t = 0; t <= 15; t++) + { + uint32_t ss1 = rotate_left((rotate_left(a, 12) + e + rotate_left(0x79cc4519U, t)), 7); + uint32_t ss2 = ss1 ^ rotate_left(a, 12); + uint32_t tt1 = sm3_functions::xorf(a, b, c) + d + ss2 + W2[t]; + uint32_t tt2 = sm3_functions::xorf(e, f, g) + h + ss1 + W[t]; + d = c; + c = rotate_left(b, 9); + b = a; + a = tt1; + h = g; + g = rotate_left(f, 19); + f = e; + e = sm3_functions::p0(tt2); + } + + for (int t = 16; t <= 63; t++) + { + uint32_t ss1 = rotate_left((rotate_left(a, 12) + e + rotate_left(0x7a879d8aU, t)), 7); + uint32_t ss2 = ss1 ^ rotate_left(a, 12); + uint32_t tt1 = sm3_functions::ff1(a, b, c) + d + ss2 + W2[t]; + uint32_t tt2 = sm3_functions::gg1(e, f, g) + h + ss1 + W[t]; + d = c; + c = rotate_left(b, 9); + b = a; + a = tt1; + h = g; + g = rotate_left(f, 19); + f = e; + e = sm3_functions::p0(tt2); + } + + H[0] ^= a; + H[1] ^= b; + H[2] ^= c; + H[3] ^= d; + H[4] ^= e; + H[5] ^= f; + H[6] ^= g; + H[7] ^= h; + } + } + + std::array H; + std::array m; + size_t pos; + uint64_t total; +}; + +} // namespace detail + +} // namespace digestpp + +#endif \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/detail/streebog_provider.hpp b/ext/include/digestpp/algorithm/detail/streebog_provider.hpp new file mode 100644 index 0000000..220ef0c --- /dev/null +++ b/ext/include/digestpp/algorithm/detail/streebog_provider.hpp @@ -0,0 +1,182 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_PROVIDERS_STREEBOG_HPP +#define DIGESTPP_PROVIDERS_STREEBOG_HPP + +#include "../../detail/functions.hpp" +#include "../../detail/absorb_data.hpp" +#include "../../detail/validate_hash_size.hpp" +#include "constants/streebog_constants.hpp" +#include + +namespace digestpp +{ + +namespace detail +{ + +namespace streebog_functions +{ + template + static inline uint64_t lps(unsigned char* ch) + { + return streebog_constants::T[0][(ch[I])] + ^ streebog_constants::T[1][(ch[8 + I])] + ^ streebog_constants::T[2][(ch[16 + I])] + ^ streebog_constants::T[3][(ch[24 + I])] + ^ streebog_constants::T[4][(ch[32 + I])] + ^ streebog_constants::T[5][(ch[40 + I])] + ^ streebog_constants::T[6][(ch[48 + I])] + ^ streebog_constants::T[7][(ch[56 + I])]; + } + + static inline void lps_block(uint64_t* block) + { + unsigned char ch[64]; + memcpy(ch, block, 64); + + block[0] = lps<0>(ch); + block[1] = lps<1>(ch); + block[2] = lps<2>(ch); + block[3] = lps<3>(ch); + block[4] = lps<4>(ch); + block[5] = lps<5>(ch); + block[6] = lps<6>(ch); + block[7] = lps<7>(ch); + } + + static inline void xor_blocks(uint64_t* block, const uint64_t* toxor) + { + block[0] ^= toxor[0]; + block[1] ^= toxor[1]; + block[2] ^= toxor[2]; + block[3] ^= toxor[3]; + block[4] ^= toxor[4]; + block[5] ^= toxor[5]; + block[6] ^= toxor[6]; + block[7] ^= toxor[7]; + } + + static inline void e(uint64_t* K, const unsigned char* m) + { + uint64_t tmp[8]; + memcpy(tmp, K, 64); + xor_blocks(K, reinterpret_cast(m)); + for (int i = 0; i < 12; i++) + { + lps_block(K); + xor_blocks(tmp, &streebog_constants::RC[i][0]); + lps_block(tmp); + xor_blocks(K, tmp); + } + } + + static inline void gN(uint64_t* h, const unsigned char* m, uint64_t N) + { + uint64_t hN[8]; + memcpy(hN, h, 64); + hN[0] ^= N; + lps_block(hN); + e(hN, m); + xor_blocks(h, hN); + xor_blocks(h, reinterpret_cast(m)); + } + + static inline void addm(const unsigned char* m, uint64_t* h) + { + const uint64_t* m64 = reinterpret_cast(m); + bool carry = false, overflow = false; + for (int i = 0; i < 8; i++) + { + uint64_t t = h[i] + m64[i]; + overflow = t < h[i] || t < m64[i]; + h[i] = t + carry; + carry = overflow; + } + } + +} + +class streebog_provider +{ +public: + static const bool is_xof = false; + + streebog_provider(size_t hashsize) + : hs(hashsize) + { + validate_hash_size(hashsize, { 256, 512 }); + } + + ~streebog_provider() + { + clear(); + } + + inline void init() + { + pos = 0; + total = 0; + memset(&h[0], hs == 512 ? 0 : 1, sizeof(uint64_t) * 8); + memset(&S[0], 0, sizeof(uint64_t) * 8); + } + + inline void update(const unsigned char* data, size_t len) + { + detail::absorb_bytes(data, len, 64, 64, m.data(), pos, total, + [this](const unsigned char* data, size_t len) { transform(data, len, false); }); + } + + inline void final(unsigned char* hash) + { + m[pos++] = 0x01; + if (pos != 64) + memset(&m[pos], 0, 64 - pos); + transform(&m[0], 1, false); + total += (pos - 1) * 8; + + memcpy(&m[0], &total, sizeof(total)); + memset(&m[sizeof(total)], 0, 64 - sizeof(total)); + transform(&m[0], 1, true); + transform(reinterpret_cast(&S[0]), 1, true); + + memcpy(hash, &h[8 - hash_size()/64], hash_size() / 8); + } + + inline void clear() + { + zero_memory(h); + zero_memory(S); + zero_memory(m); + } + + inline size_t hash_size() const { return hs; } + +private: + inline void transform(const unsigned char* mp, size_t num_blks, bool final) + { + for (size_t blk = 0; blk < num_blks; blk++) + { + streebog_functions::gN(&h[0], mp + blk * 64, final ? 0ULL : total + blk * 512); + + if (!final) + streebog_functions::addm(mp + blk * 64, &S[0]); + } + } + + std::array h; + std::array S; + std::array m; + size_t hs; + size_t pos; + uint64_t total; + +}; + +} // namespace detail + +} // namespace digestpp + +#endif \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/detail/whirlpool_provider.hpp b/ext/include/digestpp/algorithm/detail/whirlpool_provider.hpp new file mode 100644 index 0000000..d97113a --- /dev/null +++ b/ext/include/digestpp/algorithm/detail/whirlpool_provider.hpp @@ -0,0 +1,143 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_PROVIDERS_WHIRLPOOL_HPP +#define DIGESTPP_PROVIDERS_WHIRLPOOL_HPP + +#include "../../detail/functions.hpp" +#include "../../detail/absorb_data.hpp" +#include "constants/whirlpool_constants.hpp" +#include + +namespace digestpp +{ + +namespace detail +{ + +namespace whirlpool_functions +{ + template + static inline uint64_t G(const uint64_t* ll) + { + return whirlpool_constants::T[0][static_cast(ll[a % 8])] + ^ whirlpool_constants::T[1][static_cast(ll[(a - 1) % 8] >> 8)] + ^ whirlpool_constants::T[2][static_cast(ll[(a - 2) % 8] >> 16)] + ^ whirlpool_constants::T[3][static_cast(ll[(a - 3) % 8] >> 24)] + ^ whirlpool_constants::T[4][static_cast(ll[(a - 4) % 8] >> 32)] + ^ whirlpool_constants::T[5][static_cast(ll[(a - 5) % 8] >> 40)] + ^ whirlpool_constants::T[6][static_cast(ll[(a - 6) % 8] >> 48)] + ^ whirlpool_constants::T[7][static_cast(ll[(a - 7) % 8] >> 56)]; + } +} + +class whirlpool_provider +{ +public: + static const bool is_xof = false; + + whirlpool_provider() + { + } + + ~whirlpool_provider() + { + clear(); + } + + inline void init() + { + pos = 0; + total = 0; + memset(&h[0], 0, sizeof(uint64_t)*8); + } + + inline void update(const unsigned char* data, size_t len) + { + detail::absorb_bytes(data, len, 64, 64, m.data(), pos, total, + [this](const unsigned char* data, size_t len) { transform(data, len); }); + } + + inline void final(unsigned char* hash) + { + total += pos * 8; + uint64_t mlen = byteswap(total); + m[pos++] = 0x80; + if (pos > 32) + { + if (pos != 64) + memset(&m[pos], 0, 64 - pos); + transform(m.data(), 1); + pos = 0; + } + memset(&m[pos], 0, 56 - pos); + memcpy(&m[64 - 8], &mlen, 64 / 8); + transform(m.data(), 1); + memcpy(hash, h.data(), hash_size() / 8); + } + + inline void clear() + { + zero_memory(h); + zero_memory(m); + } + + inline size_t hash_size() const { return 512; } + +private: + inline void transform(const unsigned char* mp, size_t num_blks) + { + for (uint64_t b = 0; b < num_blks; b++) + { + uint64_t K[8], state[8]; + + memcpy(K, h.data(), sizeof(K)); + for (int i = 0; i < 8; ++i) + state[i] = h[i] ^ (reinterpret_cast(mp)[i]); + + for (int r = 0; r < 10; ++r) + { + uint64_t L[8]; + + L[0] = whirlpool_functions::G<0 + 8>(K) ^ whirlpool_constants::RC[r]; + L[1] = whirlpool_functions::G<1 + 8>(K); + L[2] = whirlpool_functions::G<2 + 8>(K); + L[3] = whirlpool_functions::G<3 + 8>(K); + L[4] = whirlpool_functions::G<4 + 8>(K); + L[5] = whirlpool_functions::G<5 + 8>(K); + L[6] = whirlpool_functions::G<6 + 8>(K); + L[7] = whirlpool_functions::G<7 + 8>(K); + + memcpy(K, L, sizeof(L)); + + L[0] ^= whirlpool_functions::G<0 + 8>(state); + L[1] ^= whirlpool_functions::G<1 + 8>(state); + L[2] ^= whirlpool_functions::G<2 + 8>(state); + L[3] ^= whirlpool_functions::G<3 + 8>(state); + L[4] ^= whirlpool_functions::G<4 + 8>(state); + L[5] ^= whirlpool_functions::G<5 + 8>(state); + L[6] ^= whirlpool_functions::G<6 + 8>(state); + L[7] ^= whirlpool_functions::G<7 + 8>(state); + + memcpy(state, L, sizeof(L)); + } + + for (int i = 0; i < 8; ++i) + h[i] ^= state[i] ^ reinterpret_cast(mp)[i]; + mp += 64; + } + } + + std::array h; + std::array m; + size_t pos; + uint64_t total; + +}; + +} // namespace detail + +} // namespace digestpp + +#endif \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/echo.hpp b/ext/include/digestpp/algorithm/echo.hpp new file mode 100644 index 0000000..069dc14 --- /dev/null +++ b/ext/include/digestpp/algorithm/echo.hpp @@ -0,0 +1,49 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_ALGORITHM_ECHO_HPP +#define DIGESTPP_ALGORITHM_ECHO_HPP + +#include "../hasher.hpp" +#include "detail/echo_provider.hpp" +#include "mixin/echo_mixin.hpp" + +namespace digestpp +{ + +/** + * @brief Echo hash function + * + * @hash + * + * @outputsize 8 - 512 bits + * + * @defaultsize none + * + * @throw std::runtime_error if the requested digest size is not divisible by 8 (full bytes), + * or is not within the supported range + * + * @mixinparams salt + * + * @mixin{mixin::echo_mixin} + * + * @par Example:\n + * @code // Output a 256-bit Echo digest of a string + * digestpp::echo hasher(256); + * hasher.absorb("The quick brown fox jumps over the lazy dog"); + * std::cout << hasher.hexdigest() << '\n'; + * @endcode + * + * @par Example output:\n + * @code 3c3c10b84e818cbddfd71e1aefc6cb9cd7fd1b84acb5765813e716734a97d422 + * @endcode + * + * @sa hasher + */ +typedef hasher echo; + +} // namespace digestpp + +#endif // DIGESTPP_ALGORITHM_ECHO_HPP + diff --git a/ext/include/digestpp/algorithm/esch.hpp b/ext/include/digestpp/algorithm/esch.hpp new file mode 100644 index 0000000..3a3565f --- /dev/null +++ b/ext/include/digestpp/algorithm/esch.hpp @@ -0,0 +1,83 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_ALGORITHM_ESCH_HPP +#define DIGESTPP_ALGORITHM_ESCH_HPP + +#include "../hasher.hpp" +#include "detail/esch_provider.hpp" + +/// digestpp namespace +namespace digestpp +{ + +/** + * @brief Esch hash function + * + * @hash + * + * @outputsize 256 / 384 bits + * + * @defaultsize none + * + * @throw std::runtime_error if the requested digest size is not supported + * + * @par Example:\n + * @code // Output a 256-bit Esch digest of a string + * digestpp::esch hasher(256); + * hasher.absorb("The quick brown fox jumps over the lazy dog"); + * std::cout << hasher.hexdigest() << '\n'; + * @endcode + * + * @par Example output:\n + * @code d43f87a0fe60fc5925064880c6116c136b6d94fa24a93dffcb35d178c3af932c + * @endcode + * + * @sa hasher + */ +typedef hasher> esch; + +/** + * @brief Esch-256 in XOF mode + * + * @xof + * + * @par Example:\n + * @code // Absorb a string and squeeze 32 bytes of output + * digestpp::esch_xof hasher; + * hasher.absorb("The quick brown fox jumps over the lazy dog"); + * std::cout << hasher.hexsqueeze(32) << '\n'; + * @endcode + * + * @par Example output:\n + * @code 8f2e2748fb97b99ad18aed8f9f72cad036fb00b1a21147bb0273551d07bf9d80 + * @endcode + * + * @sa hasher + */ +typedef hasher> esch256_xof; + +/** + * @brief Esch-384 in XOF mode + * + * @xof + * + * @par Example:\n + * @code // Absorb a string and squeeze 32 bytes of output + * digestpp::esch_xof hasher; + * hasher.absorb("The quick brown fox jumps over the lazy dog"); + * std::cout << hasher.hexsqueeze(32) << '\n'; + * @endcode + * + * @par Example output:\n + * @code 355b7d373fdbbdbc9332586714e676087847a71d529a818930db17a268fd021f + * @endcode + * + * @sa hasher + */ +typedef hasher> esch384_xof; + +} // namespace digestpp + +#endif // DIGESTPP_ALGORITHM_ESCH_HPP diff --git a/ext/include/digestpp/algorithm/groestl.hpp b/ext/include/digestpp/algorithm/groestl.hpp new file mode 100644 index 0000000..508a733 --- /dev/null +++ b/ext/include/digestpp/algorithm/groestl.hpp @@ -0,0 +1,43 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_ALGORITHM_GROESTL_HPP +#define DIGESTPP_ALGORITHM_GROESTL_HPP + +#include "../hasher.hpp" +#include "detail/groestl_provider.hpp" + +namespace digestpp +{ + +/** + * @brief Grøstl hash function + * + * @hash + * + * @outputsize 8 - 512 bits + * + * @defaultsize none + * + * @throw std::runtime_error if the requested digest size is not divisible by 8 (full bytes), + * or is not within the supported range + * + * @par Example:\n + * @code // Output a 256-bit Grøstl digest of a string + * digestpp::groestl hasher(256); + * hasher.absorb("The quick brown fox jumps over the lazy dog"); + * std::cout << hasher.hexdigest() << '\n'; + * @endcode + * + * @par Example output:\n + * @code 8c7ad62eb26a21297bc39c2d7293b4bd4d3399fa8afab29e970471739e28b301 + * @endcode + * + * @sa hasher + */ +typedef hasher groestl; + +} // namespace digestpp + +#endif // DIGESTPP_ALGORITHM_GROESTL_HPP \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/jh.hpp b/ext/include/digestpp/algorithm/jh.hpp new file mode 100644 index 0000000..98624e9 --- /dev/null +++ b/ext/include/digestpp/algorithm/jh.hpp @@ -0,0 +1,43 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_ALGORITHM_JG_HPP +#define DIGESTPP_ALGORITHM_JG_HPP + +#include "../hasher.hpp" +#include "detail/jh_provider.hpp" + +namespace digestpp +{ + +/** + * @brief JH hash function + * + * @hash + * + * @outputsize 8 - 512 bits + * + * @defaultsize none + * + * @throw std::runtime_error if the requested digest size is not divisible by 8 (full bytes), + * or is not within the supported range + * + * @par Example:\n + * @code // Output a 256-bit JH digest of a string + * digestpp::jh hasher(256); + * hasher.absorb("The quick brown fox jumps over the lazy dog"); + * std::cout << hasher.hexdigest() << '\n'; + * @endcode + * + * @par Example output:\n + * @code 6a049fed5fc6874acfdc4a08b568a4f8cbac27de933496f031015b38961608a0 + * @endcode + * + * @sa hasher + */ +typedef hasher jh; + +} // namespace digestpp + +#endif // DIGESTPP_ALGORITHM_JG_HPP \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/k12m14.hpp b/ext/include/digestpp/algorithm/k12m14.hpp new file mode 100644 index 0000000..df92869 --- /dev/null +++ b/ext/include/digestpp/algorithm/k12m14.hpp @@ -0,0 +1,69 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_ALGORITHM_K12M14_HPP +#define DIGESTPP_ALGORITHM_K12M14_HPP + +#include "../hasher.hpp" +#include "detail/k12m14_provider.hpp" +#include "mixin/k12m14_mixin.hpp" + +namespace digestpp +{ + +/** + * @brief KangarooTwelve function + * + * Extendable output function similar to SHAKE128 but with reduced number of round. + * + * @xof + * + * @mixinparams customization + * + * @mixin{mixin::k12m14_mixin} + * + * @par Example:\n + * @code // Absorb a string and squeeze 32 bytes of output + * digestpp::k12 hasher; + * hasher.absorb("The quick brown fox jumps over the lazy dog"); + * std::cout << hasher.hexsqueeze(32) << '\n'; + * @endcode + * + * @par Example output:\n + * @code b4f249b4f77c58df170aa4d1723db1127d82f1d98d25ddda561ada459cd11a48 + * @endcode + * + * @sa hasher, mixin::k12m14_mixin + */ +typedef hasher, mixin::k12m14_mixin> k12; + +/** + * @brief MarsupilamiFourteen function + * + * Extendable output function similar to KangarooTwelve, but providing 256-bit security. + * + * @xof + * + * @mixinparams customization + * + * @mixin{mixin::k12m14_mixin} + * + * @par Example:\n + * @code // Absorb a string and squeeze 32 bytes of output + * digestpp::m14 hasher; + * hasher.absorb("The quick brown fox jumps over the lazy dog"); + * std::cout << hasher.hexsqueeze(32) << '\n'; + * @endcode + * + * @par Example output:\n + * @code 3611bcaa666347770dbffd4562f137c5adfe2e09f3c4268ef7c7d7c0e6c5d59c + * @endcode + * + * @sa hasher, mixin::k12m14_mixin + */ +typedef hasher, mixin::k12m14_mixin> m14; + +} // namespace digestpp + +#endif // DIGESTPP_ALGORITHM_K12M14_HPP \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/kmac.hpp b/ext/include/digestpp/algorithm/kmac.hpp new file mode 100644 index 0000000..c6ac8d3 --- /dev/null +++ b/ext/include/digestpp/algorithm/kmac.hpp @@ -0,0 +1,141 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_ALGORITHM_KMAC_HPP +#define DIGESTPP_ALGORITHM_KMAC_HPP + +#include "../hasher.hpp" +#include "detail/kmac_provider.hpp" +#include "mixin/kmac_mixin.hpp" + +namespace digestpp +{ + +/** + * @brief KMAC128 in hash mode + * + * Use this variant when the required hash size is known in advance. Otherwise, use \ref kmac128_xof. + * While primary usage of KMAC is message authentication, it can also be used without a key as a regular hash function. + * + * @hash + * + * @outputsize arbitrary + * + * @defaultsize none + * + * @throw std::runtime_error if the requested digest size is not divisible by 8 (full bytes) + * + * @mixinparams customization, key + * + * @mixin{mixin::kmac_mixin} + * + * @par Example:\n + * @code // Set key and output a 256-bit KMAC128 of a string + * digestpp::kmac128 hasher(256); + * hasher.set_key(R"(@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_)"); + * hasher.absorb("The quick brown fox jumps over the lazy dog"); + * std::cout << hasher.hexdigest() << '\n'; + * @endcode + * + * @par Example output:\n + * @code bbd4ebf20aacc8e4dfd2cc91f2b6cbf33e2a45d805996b48a17b8d3e42b4b010 + * @endcode + * + * @sa hasher, kmac128_xof, mixin::kmac_mixin + */ +typedef hasher, mixin::kmac_mixin> kmac128; + +/** + * @brief KMAC256 in hash mode + * + * Use this variant when the required hash size is known in advance. Otherwise, use \ref kmac256_xof. + * While primary usage of KMAC is message authentication, it can also be used without a key as a regular hash function. + * + * @hash + * + * @outputsize arbitrary + * + * @defaultsize none + * + * @throw std::runtime_error if the requested digest size is not divisible by 8 (full bytes) + * + * @mixinparams customization, key + * + * @mixin{mixin::kmac_mixin} + * + * @par Example:\n + * @code // Set key and output a 256-bit KMAC256 of a string + * digestpp::kmac256 hasher(256); + * hasher.set_key(R("@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_")); + * hasher.absorb("The quick brown fox jumps over the lazy dog"); + * std::cout << hasher.hexdigest() << '\n'; + * @endcode + * + * @par Example output:\n + * @code bbe7d65fe0e7574254a13e0f3f79482275b96887287fc8b620a92ed5e5de3bce + * @endcode + * + * @sa hasher, kmac256_xof, mixin::kmac_mixin + */ +typedef hasher, mixin::kmac_mixin> kmac256; + +/** + * @brief KMAC128 in XOF mode (KMACXOF128) + * + * Use this variant when the required hash size is not known in advance. Otherwise, use \ref kmac128. + * This hasher can also be used without a key, but there are no advantages over \ref cshake128 in this case. + * + * @xof + * + * @mixinparams customization, key + * + * @mixin{mixin::kmac_mixin} + * + * @par Example:\n + * @code // Set key, absorb a string and squeeze 32 bytes of output + * digestpp::kmac128_xof hasher; + * hasher.set_key(R"(@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_)"); + * hasher.absorb("The quick brown fox jumps over the lazy dog"); + * std::cout << hasher.hexsqueeze(32) << '\n'; + * @endcode + * + * @par Example output:\n + * @code a5dd2e2c92e4fe5d203ab7cc4e05df888b021390ba08a00dcb39a94ed07bd364 + * @endcode + * + * @sa hasher, kmac128, mixin::kmac_mixin + */ +typedef hasher, mixin::kmac_mixin> kmac128_xof; + +/** + * @brief KMAC256 in XOF mode (KMACXOF256) + * + * Use this variant when the required hash size is not known in advance. Otherwise, use \ref kmac256. + * This hasher can also be used without a key, but there are no advantages over \ref cshake256 in this case. + * + * @xof + * + * @mixinparams customization, key + * + * @mixin{mixin::kmac_mixin} + * + * @par Example:\n + * @code // Set key, absorb a string and squeeze 32 bytes of output + * digestpp::kmac256_xof hasher; + * hasher.set_key(R"(@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_)"); + * hasher.absorb("The quick brown fox jumps over the lazy dog"); + * std::cout << hasher.hexsqueeze(32) << '\n'; + * @endcode + * + * @par Example output:\n + * @code 81ce507692e27fb404e4a765c3be3450ce5c090a61b8311f93eb4e35604877ad + * @endcode + * + * @sa hasher, kmac256, mixin::kmac_mixin + */ +typedef hasher, mixin::kmac_mixin> kmac256_xof; + +} // namespace digestpp + +#endif // DIGESTPP_ALGORITHM_KMAC_HPP \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/kupyna.hpp b/ext/include/digestpp/algorithm/kupyna.hpp new file mode 100644 index 0000000..88377ef --- /dev/null +++ b/ext/include/digestpp/algorithm/kupyna.hpp @@ -0,0 +1,43 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_ALGORITHM_KUPYNA_HPP +#define DIGESTPP_ALGORITHM_KUPYNA_HPP + +#include "../hasher.hpp" +#include "detail/kupyna_provider.hpp" + +namespace digestpp +{ + +/** + * @brief Kupyna hash function + * + * @hash + * + * @outputsize 256 / 512 bits + * + * @defaultsize none + * + * @throw std::runtime_error if the requested digest size is not supported + * + * @par Example:\n + * @code // Output a 256-bit Kupyna digest of a string + * digestpp::kupyna hasher(256); + * hasher.absorb("The quick brown fox jumps over the lazy dog"); + * std::cout << hasher.hexdigest() << '\n'; + * @endcode + * + * @par Example output:\n + * @code 996899f2d7422ceaf552475036b2dc120607eff538abf2b8dff471a98a4740c6 + * @endcode + * + * @sa hasher + */ + +typedef hasher kupyna; + +} // namespace digestpp + +#endif // DIGESTPP_ALGORITHM_KUPYNA_HPP \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/md5.hpp b/ext/include/digestpp/algorithm/md5.hpp new file mode 100644 index 0000000..636e74b --- /dev/null +++ b/ext/include/digestpp/algorithm/md5.hpp @@ -0,0 +1,42 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_ALGORITHM_MD5_HPP +#define DIGESTPP_ALGORITHM_MD5_HPP + +#include "../hasher.hpp" +#include "detail/md5_provider.hpp" + +namespace digestpp +{ + +/** + * @brief MD5 hash function + * + * Note that MD5 hash function is considered insecure and is not recommended for new applications. + * + * @hash + * + * @outputsize 128 bits + * + * @defaultsize 128 bits + * + * @par Example:\n + * @code // Output an MD5 digest of a string + * digestpp::md5 hasher; + * hasher.absorb("The quick brown fox jumps over the lazy dog"); + * std::cout << hasher.hexdigest() << '\n'; + * @endcode + * + * @par Example output:\n + * @code 9e107d9d372bb6826bd81d3542a419d6 + * @endcode + * + * @sa hasher + */ +typedef hasher md5; + +} // namespace digestpp + +#endif \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/mixin/blake2_mixin.hpp b/ext/include/digestpp/algorithm/mixin/blake2_mixin.hpp new file mode 100644 index 0000000..66e6ea2 --- /dev/null +++ b/ext/include/digestpp/algorithm/mixin/blake2_mixin.hpp @@ -0,0 +1,127 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_MIXINS_BLAKE2_HPP +#define DIGESTPP_MIXINS_BLAKE2_HPP + +namespace digestpp +{ + +namespace mixin +{ + +/** + * \brief Defines additional public functions for BLAKE2 family of algorithms. + * \sa hasher, blake2s, blake2b, blake2sx, blake2bx, blake2sx_xof, blake2bx_xof + */ +template +class blake2_mixin +{ +public: + /** + * \brief Set salt from std::string + * + * Supported salt size is 8 bytes for BLAKE2s and 16 bytes for BLAKE2b. + * + * \param[in] salt String with salt + * \throw std::runtime_error if salt size is not supported. + * \return Reference to hasher + */ + inline hasher& set_salt(const std::string& salt) + { + return set_salt(salt.c_str(), salt.size()); + } + + /** + * \brief Set salt from raw buffer + * + * Supported salt size is 8 bytes for BLAKE2s and 16 bytes for BLAKE2b. + * + * \param[in] salt Pointer to salt bytes + * \param[in] salt_len Salt length (in bytes) + * \throw std::runtime_error if salt size is not supported. + * \return Reference to hasher + */ + template::value>::type* = nullptr> + inline hasher& set_salt(const C* salt, size_t salt_len) + { + auto& blake = static_cast&>(*this); + blake.provider.set_salt(reinterpret_cast(salt), salt_len); + blake.provider.init(); + return blake; + } + + /** + * \brief Set personalization from std::string + * + * Supported personalization size is 8 bytes for BLAKE2s and 16 bytes for BLAKE2b. + * + * \param[in] personalization String with personalization + * \throw std::runtime_error if personalization size is not supported. + * \return Reference to hasher + */ + inline hasher& set_personalization(const std::string& personalization) + { + return set_personalization(personalization.c_str(), personalization.size()); + } + + /** + * \brief Set personalization from raw buffer + * + * Supported personalization size is 8 bytes for BLAKE2s and 16 bytes for BLAKE2b. + * + * \param[in] personalization Pointer to personalization bytes + * \param[in] personalization_len Personalization length (in bytes) + * \throw std::runtime_error if personalization size is not supported. + * \return Reference to hasher + */ + template::value>::type* = nullptr> + inline hasher& set_personalization(const C* personalization, size_t personalization_len) + { + auto& blake = static_cast&>(*this); + blake.provider.set_personalization(reinterpret_cast(personalization), personalization_len); + blake.provider.init(); + return blake; + } + + /** + * \brief Set key from std::string + * + * Maximum key size is 32 bytes for BLAKE2s and 64 bytes for BLAKE2b. + * + * \param[in] key String with key + * \throw std::runtime_error if key size is not supported. + * \return Reference to hasher + */ + inline hasher& set_key(const std::string& key) + { + auto& blake = static_cast&>(*this); + blake.provider.set_key(key); + blake.provider.init(); + return blake; + } + + /** + * \brief Set key from raw buffer + * + * Maximum key size is 32 bytes for BLAKE2s and 64 bytes for BLAKE2b. + * + * \param[in] key Pointer to key bytes + * \param[in] key_len Key length (in bytes) + * \throw std::runtime_error if key size is not supported. + * \return Reference to hasher + */ + template::value>::type* = nullptr> + inline hasher& set_key(const C* key, size_t key_len) + { + return set_key(std::string(reinterpret_cast(key), key_len)); + } +}; + + +} // namespace mixin + +} // namespace digestpp + +#endif \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/mixin/blake_mixin.hpp b/ext/include/digestpp/algorithm/mixin/blake_mixin.hpp new file mode 100644 index 0000000..a954d96 --- /dev/null +++ b/ext/include/digestpp/algorithm/mixin/blake_mixin.hpp @@ -0,0 +1,61 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_MIXINS_BLAKE_HPP +#define DIGESTPP_MIXINS_BLAKE_HPP + +namespace digestpp +{ + +namespace mixin +{ + +/** + * \brief Defines additional public functions for BLAKE algorithm. + * \sa hasher, blake + */ +template +class blake_mixin +{ +public: + + /** + * \brief Set salt from std::string + * + * Supported salt size is 16 bytes for BLAKE-224, BLAKE-256 and 32 bytes for BLAKE-384, BLAKE-512. + * + * \param[in] salt String with salt + * \throw std::runtime_error if salt size is not supported. + * \return Reference to hasher + */ + inline hasher& set_salt(const std::string& salt) + { + return set_salt(salt.c_str(), salt.size()); + } + + /** + * \brief Set salt from raw buffer + * + * Supported salt size is 16 bytes for BLAKE-224, BLAKE-256 and 32 bytes for BLAKE-384, BLAKE-512. + * + * \param[in] salt Pointer to salt bytes + * \param[in] salt_len Salt length (in bytes) + * \throw std::runtime_error if salt size is not supported. + * \return Reference to hasher + */ + template::value>::type* = nullptr> + inline hasher& set_salt(const C* salt, size_t salt_len) + { + auto& blake = static_cast&>(*this); + blake.provider.set_salt(reinterpret_cast(salt), salt_len); + blake.provider.init(); + return blake; + } +}; + +} // namespace mixin + +} // namespace digestpp + +#endif \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/mixin/cshake_mixin.hpp b/ext/include/digestpp/algorithm/mixin/cshake_mixin.hpp new file mode 100644 index 0000000..b26d83f --- /dev/null +++ b/ext/include/digestpp/algorithm/mixin/cshake_mixin.hpp @@ -0,0 +1,81 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_MIXIN_SHAKE_HPP +#define DIGESTPP_MIXIN_SHAKE_HPP + +namespace digestpp +{ + +namespace mixin +{ + +/** + * \brief Defines additional public functions for cSHAKE128 and cSHAKE256. + * \sa hasher, cshake128, cshake256 + */ +template +class cshake_mixin +{ +public: + /** + * \brief Set NIST function name from std::string + * + * \param[in] function_name NIST function name string + * \return Reference to hasher + */ + inline hasher& set_function_name(const std::string& function_name) + { + auto& shake = static_cast&>(*this); + shake.provider.set_function_name(function_name); + shake.provider.init(); + return shake; + } + + /** + * \brief Set NIST function name from raw buffer + * + * \param[in] function_name Pointer to NIST function name bytes + * \param[in] function_name_len NIST function name length (in bytes) + * \return Reference to hasher + */ + template::value>::type* = nullptr> + inline hasher& set_function_name(const C* function_name, size_t function_name_len) + { + return set_function_name(std::string(reinterpret_cast(function_name), function_name_len)); + } + + /** + * \brief Set customization from std::string + * + * \param[in] customization Customization string + * \return Reference to hasher + */ + inline hasher& set_customization(const std::string& customization) + { + auto& shake = static_cast&>(*this); + shake.provider.set_customization(customization); + shake.provider.init(); + return shake; + } + + /** + * \brief Set customization from raw buffer + * + * \param[in] customization Pointer to customization bytes + * \param[in] customization_len Customization length (in bytes) + * \return Reference to hasher + */ + template::value>::type* = nullptr> + inline hasher& set_customization(const C* customization, size_t customization_len) + { + return set_customization(std::string(reinterpret_cast(customization), customization_len)); + } +}; + +} // namespace mixin + +} // namespace digestpp + +#endif // DIGESTPP_MIXIN_SHAKE_HPP \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/mixin/echo_mixin.hpp b/ext/include/digestpp/algorithm/mixin/echo_mixin.hpp new file mode 100644 index 0000000..3d1e360 --- /dev/null +++ b/ext/include/digestpp/algorithm/mixin/echo_mixin.hpp @@ -0,0 +1,62 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_MIXINS_ECHO_HPP +#define DIGESTPP_MIXINS_ECHO_HPP + +namespace digestpp +{ + +namespace mixin +{ + +/** + * \brief Defines additional public functions for ECHO algorithm. + * \sa hasher, echo + */ +template +class echo_mixin +{ +public: + + /** + * \brief Set salt from std::string + * + * Supported salt size is 16 bytes. + * + * \param[in] salt String with salt + * \throw std::runtime_error if salt size is not supported. + * \return Reference to hasher + */ + inline hasher& set_salt(const std::string& salt) + { + return set_salt(salt.c_str(), salt.size()); + } + + /** + * \brief Set salt from raw buffer + * + * Supported salt size is 16 bytes. + * + * \param[in] salt Pointer to salt bytes + * \param[in] salt_len Salt length (in bytes) + * \throw std::runtime_error if salt size is not supported. + * \return Reference to hasher + */ + template::value>::type* = nullptr> + inline hasher& set_salt(const C* salt, size_t salt_len) + { + auto& echo = static_cast&>(*this); + echo.provider.set_salt(reinterpret_cast(salt), salt_len); + echo.provider.init(); + return echo; + } +}; + +} // namespace mixin + +} // namespace digestpp + +#endif + diff --git a/ext/include/digestpp/algorithm/mixin/k12m14_mixin.hpp b/ext/include/digestpp/algorithm/mixin/k12m14_mixin.hpp new file mode 100644 index 0000000..3b00f15 --- /dev/null +++ b/ext/include/digestpp/algorithm/mixin/k12m14_mixin.hpp @@ -0,0 +1,55 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_MIXINS_K12M14_HPP +#define DIGESTPP_MIXINS_K12M14_HPP + +namespace digestpp +{ + +namespace mixin +{ + +/** + * \brief Defines additional public functions for KangarooTwelve and MarsupilamiFourteen. + * \sa hasher, k12, m14 + */ +template +class k12m14_mixin +{ +public: + + /** + * \brief Set customization from std::string + * + * \param[in] customization Customization string + * \return Reference to hasher + */ + inline hasher& set_customization(const std::string& customization) + { + auto& k12m14 = static_cast&>(*this); + k12m14.provider.set_customization(customization); + k12m14.provider.init(); + return k12m14; + } + + /** + * \brief Set customization from raw buffer + * + * \param[in] customization Pointer to customization bytes + * \param[in] customization_len Customization length (in bytes) + * \return Reference to hasher + */ + template::value>::type* = nullptr> + inline hasher& set_customization(const C* customization, size_t customization_len) + { + return set_customization(std::string(reinterpret_cast(customization), customization_len)); + } +}; + +} // namespace mixin + +} // namespace digestpp + +#endif // DIGESTPP_MIXINS_K12M14_HPP \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/mixin/kmac_mixin.hpp b/ext/include/digestpp/algorithm/mixin/kmac_mixin.hpp new file mode 100644 index 0000000..7e4b2eb --- /dev/null +++ b/ext/include/digestpp/algorithm/mixin/kmac_mixin.hpp @@ -0,0 +1,81 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_MIXINS_KMAC_HPP +#define DIGESTPP_MIXINS_KMAC_HPP + +namespace digestpp +{ + +namespace mixin +{ + +/** + * \brief Defines additional public functions for KMAC family of algorithms. + * \sa hasher, kmac128, kmac256, kmac128_xof, kmac256_xof + */ +template +class kmac_mixin +{ +public: + /** + * \brief Set key from std::string + * + * \param[in] key Key string + * \return Reference to hasher + */ + inline hasher& set_key(const std::string& key) + { + auto& kmac = static_cast&>(*this); + kmac.provider.set_key(key); + kmac.provider.init(); + return kmac; + } + + /** + * \brief Set key from raw buffer + * + * \param[in] key Pointer to key bytes + * \param[in] key_len Key length (in bytes) + * \return Reference to hasher + */ + template::value>::type* = nullptr> + inline hasher& set_key(const C* key, size_t key_len) + { + return set_key(std::string(reinterpret_cast(key), key_len)); + } + + /** + * \brief Set customization from std::string + * + * \param[in] customization Customization string + * \return Reference to hasher + */ + inline hasher& set_customization(const std::string& customization) + { + auto& kmac = static_cast&>(*this); + kmac.provider.set_customization(customization); + kmac.provider.init(); + return kmac; + } + + /** + * \brief Set customization from raw buffer + * + * \param[in] customization Pointer to customization bytes + * \param[in] customization_len Customization length (in bytes) + * \return Reference to hasher + */ + template::value>::type* = nullptr> + inline hasher& set_customization(const C* customization, size_t customization_len) + { + return set_customization(std::string(reinterpret_cast(customization), customization_len)); + } +}; + +} // namespace mixin + +} // namespace digestpp + +#endif // DIGESTPP_MIXINS_KMAC_HPP \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/mixin/null_mixin.hpp b/ext/include/digestpp/algorithm/mixin/null_mixin.hpp new file mode 100644 index 0000000..390aaa7 --- /dev/null +++ b/ext/include/digestpp/algorithm/mixin/null_mixin.hpp @@ -0,0 +1,25 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_MIXINS_NULL_HPP +#define DIGESTPP_MIXINS_NULL_HPP + +namespace digestpp +{ +namespace mixin +{ + +/** + * \brief Empty mixin that does not have any additional fuctions. + * \sa hasher + */ +template +struct null_mixin +{ +}; + +} // namespace mixin +} // namespace digestpp + +#endif // DIGESTPP_MIXINS_NULL_HPP \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/mixin/skein_mixin.hpp b/ext/include/digestpp/algorithm/mixin/skein_mixin.hpp new file mode 100644 index 0000000..a013a92 --- /dev/null +++ b/ext/include/digestpp/algorithm/mixin/skein_mixin.hpp @@ -0,0 +1,108 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_MIXINS_SKEIN_HPP +#define DIGESTPP_MIXINS_SKEIN_HPP + +namespace digestpp +{ + +namespace mixin +{ + +/** + * \brief Defines additional public functions for Skein family of algorithms. + * \sa hasher, skein256, skein512, skein1024, skein256_xof, skein512_xof, skein1024_xof + */ +template +class skein_mixin +{ +public: + /** + * \brief Set personalization from std::string + * + * \param[in] personalization Personalization string + * \return Reference to hasher + */ + inline hasher& set_personalization(const std::string& personalization) + { + auto& skein = static_cast&>(*this); + skein.provider.set_personalization(personalization); + skein.provider.init(); + return skein; + } + + /** + * \brief Set personalization from raw buffer + * + * \param[in] personalization Pointer to personalization bytes + * \param[in] personalization_len Personalization length (in bytes) + * \return Reference to hasher + */ + template::value>::type* = nullptr> + inline hasher& set_personalization(const C* personalization, size_t personalization_len) + { + return set_personalization(std::string(reinterpret_cast(personalization), personalization_len)); + } + + /** + * \brief Set key from std::string + * + * \param[in] key Key string + * \return Reference to hasher + */ + inline hasher& set_key(const std::string& key) + { + auto& skein = static_cast&>(*this); + skein.provider.set_key(key); + skein.provider.init(); + return skein; + } + + /** + * \brief Set key from raw buffer + * + * \param[in] key Pointer to key bytes + * \param[in] key_len Key length (in bytes) + * \return Reference to hasher + */ + template::value>::type* = nullptr> + inline hasher& set_key(const C* key, size_t key_len) + { + return set_key(std::string(reinterpret_cast(key), key_len)); + } + + /** + * \brief Set nonce from std::string + * + * \param[in] nonce Nonce string + * \return Reference to hasher + */ + inline hasher& set_nonce(const std::string& nonce) + { + auto& skein = static_cast&>(*this); + skein.provider.set_nonce(nonce); + skein.provider.init(); + return skein; + } + + /** + * \brief Set nonce from raw buffer + * + * \param[in] nonce Pointer to nonce bytes + * \param[in] nonce_len Nonce length (in bytes) + * \return Reference to hasher + */ + template::value>::type* = nullptr> + inline hasher& set_nonce(const C* nonce, size_t nonce_len) + { + return set_nonce(std::string(reinterpret_cast(nonce), nonce_len)); + } +}; + +} // namespace mixin + +} // namespace digestpp + +#endif \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/sha1.hpp b/ext/include/digestpp/algorithm/sha1.hpp new file mode 100644 index 0000000..536b623 --- /dev/null +++ b/ext/include/digestpp/algorithm/sha1.hpp @@ -0,0 +1,42 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_ALGORITHM_SHA1_HPP +#define DIGESTPP_ALGORITHM_SHA1_HPP + +#include "../hasher.hpp" +#include "detail/sha1_provider.hpp" + +namespace digestpp +{ + +/** + * @brief SHA-1 hash function + * + * Note that SHA-1 hash function is considered insecure and is not recommended for new applications. + * + * @hash + * + * @outputsize 160 bits + * + * @defaultsize 160 bits + * + * @par Example:\n + * @code // Output a SHA1 digest of a string + * digestpp::sha1 hasher; + * hasher.absorb("The quick brown fox jumps over the lazy dog"); + * std::cout << hasher.hexdigest() << '\n'; + * @endcode + * + * @par Example output:\n + * @code 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 + * @endcode + * + * @sa hasher + */ +typedef hasher sha1; + +} // namespace digestpp + +#endif \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/sha2.hpp b/ext/include/digestpp/algorithm/sha2.hpp new file mode 100644 index 0000000..dee9c81 --- /dev/null +++ b/ext/include/digestpp/algorithm/sha2.hpp @@ -0,0 +1,118 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_ALGORITHM_SHA2_HPP +#define DIGESTPP_ALGORITHM_SHA2_HPP + +#include "../hasher.hpp" +#include "detail/sha2_provider.hpp" + +namespace digestpp +{ + +/** + * @brief SHA-512 hash function + * + * @hash + * + * @outputsize 8 - 512 bits + * + * @defaultsize 512 bits + * + * @throw std::runtime_error if the requested digest size is not divisible by 8 (full bytes), + * or is not within the supported range + * + * @par Example:\n + * @code // Output a SHA-512/256 digest of a string + * digestpp::sha512 hasher(256); + * hasher.absorb("The quick brown fox jumps over the lazy dog"); + * std::cout << hasher.hexdigest() << '\n'; + * @endcode + * + * @par Example output:\n + * @code dd9d67b371519c339ed8dbd25af90e976a1eeefd4ad3d889005e532fc5bef04d + * @endcode + * + * @sa hasher + */ +typedef hasher> sha512; + +/** + * @brief SHA-384 hash function + * + * @hash + * + * @outputsize 384 bits + * + * @defaultsize 384 bits + * + * @par Example:\n + * @code // Output a SHA-384 digest of a string + * digestpp::sha384 hasher; + * hasher.absorb("The quick brown fox jumps over the lazy dog"); + * std::cout << hasher.hexdigest() << '\n'; + * @endcode + * + * @par Example output:\n + * @code ca737f1014a48f4c0b6dd43cb177b0afd9e5169367544c494011e3317dbf9a509cb1e5dc1e85a941bbee3d7f2afbc9b1 + * @endcode + * + * @sa hasher + */ +typedef hasher> sha384; + +/** + * @brief SHA-256 hash function + * + * Note that this function is slower than SHA-512/256 on 64-bit systems. + * + * @hash + * + * @outputsize 256 bits + * + * @defaultsize 256 bits + * + * @par Example:\n + * @code // Output a SHA-256 digest of a string + * digestpp::sha256 hasher; + * hasher.absorb("The quick brown fox jumps over the lazy dog"); + * std::cout << hasher.hexdigest() << '\n'; + * @endcode + * + * @par Example output:\n + * @code d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592 + * @endcode + * + * @sa hasher + */ +typedef hasher> sha256; + +/** + * @brief SHA-224 hash function + * + * @hash + * + * @outputsize 224 bits + * + * @defaultsize 224 bits + * + * @par Example:\n + * @code // Output a SHA-224 digest of a string + * digestpp::sha224 hasher; + * hasher.absorb("The quick brown fox jumps over the lazy dog"); + * std::cout << hasher.hexdigest() << '\n'; + * @endcode + * + * @par Example output:\n + * @code 730e109bd7a8a32b1cb9d9a09aa2325d2430587ddbc0c38bad911525 + * @endcode + * + * @sa hasher + */ +typedef hasher> sha224; + + +} // namespace digestpp + +#endif \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/sha3.hpp b/ext/include/digestpp/algorithm/sha3.hpp new file mode 100644 index 0000000..8d5dff7 --- /dev/null +++ b/ext/include/digestpp/algorithm/sha3.hpp @@ -0,0 +1,42 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_ALGORITHM_SHA3_HPP +#define DIGESTPP_ALGORITHM_SHA3_HPP + +#include "../hasher.hpp" +#include "detail/sha3_provider.hpp" + +namespace digestpp +{ + +/** + * @brief SHA-3 hash function + * + * @hash + * + * @outputsize 224 / 256 / 384 / 512 bits + * + * @defaultsize none + * + * @throw std::runtime_error if the requested digest size is not supported + * + * @par Example:\n + * @code // Output a 256-bit SHA-3 digest of a string + * digestpp::sha3 hasher(256); + * hasher.absorb("The quick brown fox jumps over the lazy dog"); + * std::cout << hasher.hexdigest() << '\n'; + * @endcode + * + * @par Example output:\n + * @code 69070dda01975c8c120c3aada1b282394e7f032fa9cf32f4cb2259a0897dfc04 + * @endcode + * + * @sa hasher + */ +typedef hasher sha3; + +} // namespace digestpp + +#endif // DIGESTPP_ALGORITHM_SHA3_HPP \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/shake.hpp b/ext/include/digestpp/algorithm/shake.hpp new file mode 100644 index 0000000..c3efcab --- /dev/null +++ b/ext/include/digestpp/algorithm/shake.hpp @@ -0,0 +1,113 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_ALGORITHM_SHAKE_HPP +#define DIGESTPP_ALGORITHM_SHAKE_HPP + +#include "../hasher.hpp" +#include "detail/shake_provider.hpp" +#include "mixin/cshake_mixin.hpp" + +namespace digestpp +{ + +/** + * @brief SHAKE128 function + * + * @xof + * + * @par Example:\n + * @code // Absorb a string and squeeze 32 bytes of output + * digestpp::shake128 hasher; + * hasher.absorb("The quick brown fox jumps over the lazy dog"); + * std::cout << hasher.hexsqueeze(32) << '\n'; + * @endcode + * + * @par Example output:\n + * @code f4202e3c5852f9182a0430fd8144f0a74b95e7417ecae17db0f8cfeed0e3e66e + * @endcode + * + * @sa hasher, cshake128 + */ +typedef hasher> shake128; + +/** + * @brief SHAKE256 function + * + * @xof + * + * @par Example:\n + * @code // Absorb a string and squeeze 32 bytes of output + * digestpp::shake256 hasher; + * hasher.absorb("The quick brown fox jumps over the lazy dog"); + * std::cout << hasher.hexsqueeze(32) << '\n'; + * @endcode + * + * @par Example output:\n + * @code 2f671343d9b2e1604dc9dcf0753e5fe15c7c64a0d283cbbf722d411a0e36f6ca + * @endcode + * + * @sa hasher, cshake256 + */ +typedef hasher> shake256; + +/** + * @brief Customizable cSHAKE128 function + * + * Extendable output function similar to SHAKE128 but with possibility to use a customization string. + * When used without a customization string, the output is identical to \ref shake128. + * + * @xof + * + * @mixinparams function name, customization + * + * @mixin{mixin::cshake_mixin} + * + * @par Example:\n + * @code // Absorb a string and squeeze 32 bytes of output + * digestpp::cshake128 hasher; + * hasher.set_customization("My Custom SHAKE"); + * hasher.absorb("The quick brown fox jumps over the lazy dog"); + * std::cout << hasher.hexsqueeze(32) << '\n'; + * @endcode + * + * @par Example output:\n + * @code 5b831bfe752f7f05d81f18f0e83a92eb48b9e3d460c10022ecb4852aa8b1f9d4 + * @endcode + * + * @sa hasher, mixin::cshake_mixin + */ +typedef hasher, mixin::cshake_mixin> cshake128; + +/** + * @brief Customizable cSHAKE256 function + * + * Extendable output function similar to SHAKE256 but with possibility to use a customization string. + * When used without a customization string, the output is identical to \ref shake256. + * + * @xof + * + * @mixinparams function name, customization + * + * @mixin{mixin::cshake_mixin} + * + * @par Example:\n + * @code // Absorb a string and squeeze 32 bytes of output + * digestpp::cshake256 hasher; + * hasher.set_customization("My Custom SHAKE"); + * hasher.absorb("The quick brown fox jumps over the lazy dog"); + * std::cout << hasher.hexsqueeze(32) << '\n'; + * @endcode + * + * @par Example output:\n + * @code bcebde2c2e18f6efd99ee9e0def1383e86595d72e49b4754f7f727a962c3cd3d + * @endcode + * + * @sa hasher, mixin::cshake_mixin + */ +typedef hasher, mixin::cshake_mixin> cshake256; + +} // namespace digestpp + +#endif // DIGESTPP_ALGORITHM_SHAKE_HPP \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/skein.hpp b/ext/include/digestpp/algorithm/skein.hpp new file mode 100644 index 0000000..a2d5396 --- /dev/null +++ b/ext/include/digestpp/algorithm/skein.hpp @@ -0,0 +1,191 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_ALGORITHM_SKEIN_HPP +#define DIGESTPP_ALGORITHM_SKEIN_HPP + +#include "../hasher.hpp" +#include "detail/skein_provider.hpp" +#include "mixin/skein_mixin.hpp" + +namespace digestpp +{ + +/** + * @brief Skein1024 hash function + * + * Use this variant when the required hash size is known in advance. Otherwise, use \ref skein1024_xof + * + * @hash + * + * @outputsize arbitrary + * + * @defaultsize 1024 bits + * + * @throw std::runtime_error if the requested digest size is not divisible by 8 (full bytes) + * + * @mixinparams personalization, nonce, key + * + * @mixin{mixin::skein_mixin} + * + * @par Example:\n + * @code // Output a 256-bit Skein1024 digest of a string + * digestpp::skein1024 hasher(256); + * hasher.absorb("The quick brown fox jumps over the lazy dog"); + * std::cout << hasher.hexdigest() << '\n'; + * @endcode + * + * @par Example output:\n + * @code 054922d4393e36af62143986221555bee407671f6e57631bd7273e215a714833 + * @endcode + * + * @sa hasher, mixin::skein_mixin, skein1024_xof + */ +typedef hasher, mixin::skein_mixin> skein1024; + +/** + * @brief Skein512 hash function + * + * Use this variant when the required hash size is known in advance. Otherwise, use \ref skein512_xof + * + * @hash + * + * @outputsize arbitrary + * + * @defaultsize 512 bits + * + * @throw std::runtime_error if the requested digest size is not divisible by 8 (full bytes) + * + * @mixinparams personalization, nonce, key + * + * @mixin{mixin::skein_mixin} + * + * @par Example:\n + * @code // Output a 256-bit Skein512 digest of a string + * digestpp::skein512 hasher(256); + * hasher.absorb("The quick brown fox jumps over the lazy dog"); + * std::cout << hasher.hexdigest() << '\n'; + * @endcode + * + * @par Example output:\n + * @code b3250457e05d3060b1a4bbc1428bc75a3f525ca389aeab96cfa34638d96e492a + * @endcode + * + * @sa hasher, mixin::skein_mixin, skein512_xof + */ +typedef hasher, mixin::skein_mixin> skein512; + +/** + * @brief Skein256 hash function + * + * Use this variant when the required hash size is known in advance. Otherwise, use \ref skein256_xof + * + * @hash + * + * @outputsize arbitrary + * + * @defaultsize 256 bits + * + * @throw std::runtime_error if the requested digest size is not divisible by 8 (full bytes) + * + * @mixinparams personalization, nonce, key + * + * @mixin{mixin::skein_mixin} + * + * @par Example:\n + * @code // Output a 512-bit Skein256 digest of a string + * digestpp::skein256 hasher(512); + * hasher.absorb("The quick brown fox jumps over the lazy dog"); + * std::cout << hasher.hexdigest() << '\n'; + * @endcode + * + * @par Example output:\n + * @code f8138e72cdd9e11cf09e4be198c234acb0d21a9f75f936e989cf532f1fa9f4fb21d255811f0f1592fb3617d04704add875ae7bd16ddbbeaed4eca6eb9675d2c6 + * @endcode + * + * @sa hasher, mixin::skein_mixin, skein256_xof + */ +typedef hasher, mixin::skein_mixin> skein256; + +/** + * @brief Skein1024 in XOF mode + * + * Use this variant when the required hash size is not known in advance. Otherwise, use \ref skein1024 + * + * @xof + * + * @mixinparams personalization, nonce, key + * + * @mixin{mixin::skein_mixin} + * + * @par Example:\n + * @code // Absorb a string and squeeze 32 bytes of output + * digestpp::skein1024_xof hasher; + * hasher.absorb("The quick brown fox jumps over the lazy dog"); + * std::cout << hasher.hexsqueeze(32) << '\n'; + * @endcode + * + * @par Example output:\n + * @code 20cd7366b0a3713037fdbf8c635ea190943261455689792a327d93a9fd74dedf + * @endcode + * + * @sa hasher, mixin::skein_mixin, skein1024 + */ +typedef hasher, mixin::skein_mixin> skein1024_xof; + +/** + * @brief Skein512 in XOF mode + * + * Use this variant when the required hash size is not known in advance. Otherwise, use \ref skein512 + * + * @xof + * + * @mixinparams personalization, nonce, key + * + * @mixin{mixin::skein_mixin} + * + * @par Example:\n + * @code // Absorb a string and squeeze 32 bytes of output + * digestpp::skein512_xof hasher; + * hasher.absorb("The quick brown fox jumps over the lazy dog"); + * std::cout << hasher.hexsqueeze(32) << '\n'; + * @endcode + * + * @par Example output:\n + * @code cd7447a48e387ca4461e75ede8424566f7ed816a80bfac5bed291ac107f96170 + * @endcode + * + * @sa hasher, mixin::skein_mixin, skein512 + */ +typedef hasher, mixin::skein_mixin> skein512_xof; + +/** + * @brief Skein256 in XOF mode + * + * Use this variant when the required hash size is not known in advance. Otherwise, use \ref skein256 + * + * @xof + * + * @mixinparams personalization, nonce, key + * + * @mixin{mixin::skein_mixin} + * + * @par Example:\n + * @code // Absorb a string and squeeze 32 bytes of output + * digestpp::skein256_xof hasher; + * hasher.absorb("The quick brown fox jumps over the lazy dog"); + * std::cout << hasher.hexsqueeze(32) << '\n'; + * @endcode + * + * @par Example output:\n + * @code 217021fbabe331c5753024fe4c17a005a698b037859ca8f4f0fb9112dce5605c + * @endcode + * + * @sa hasher, mixin::skein_mixin, skein256 + */ +typedef hasher, mixin::skein_mixin> skein256_xof; + +} // namespace digestpp + +#endif \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/sm3.hpp b/ext/include/digestpp/algorithm/sm3.hpp new file mode 100644 index 0000000..69ded58 --- /dev/null +++ b/ext/include/digestpp/algorithm/sm3.hpp @@ -0,0 +1,40 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_ALGORITHM_SM3_HPP +#define DIGESTPP_ALGORITHM_SM3_HPP + +#include "../hasher.hpp" +#include "detail/sm3_provider.hpp" + +namespace digestpp +{ + +/** + * @brief SM3 hash function + * + * @hash + * + * @outputsize 256 bits + * + * @defaultsize 256 bits + * + * @par Example:\n + * @code // Output a SM3 digest of a string + * digestpp::sm3 hasher; + * hasher.absorb("The quick brown fox jumps over the lazy dog"); + * std::cout << hasher.hexdigest() << '\n'; + * @endcode + * + * @par Example output:\n + * @code 5fdfe814b8573ca021983970fc79b2218c9570369b4859684e2e4c3fc76cb8ea + * @endcode + * + * @sa hasher + */ +typedef hasher sm3; + +} // namespace digestpp + +#endif \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/streebog.hpp b/ext/include/digestpp/algorithm/streebog.hpp new file mode 100644 index 0000000..bc9e1c8 --- /dev/null +++ b/ext/include/digestpp/algorithm/streebog.hpp @@ -0,0 +1,41 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_ALGORITHM_STREEBOG_HPP +#define DIGESTPP_ALGORITHM_STREEBOG_HPP + +#include "../hasher.hpp" +#include "detail/streebog_provider.hpp" + +namespace digestpp +{ + +/** @brief Streebog hash function + * + * @hash + * + * @outputsize 256 / 512 bits + * + * @defaultsize none + * + * @throw std::runtime_error if the requested digest size is not supported + * + * @par Example:\n + * @code // Output a 256-bit Streebog digest of a string + * digestpp::streebog hasher(256); + * hasher.absorb("The quick brown fox jumps over the lazy dog"); + * std::cout << hasher.hexdigest() << '\n'; + * @endcode + * + * @par Example output:\n + * @code 3e7dea7f2384b6c5a3d0e24aaa29c05e89ddd762145030ec22c71a6db8b2c1f4 + * @endcode + * + * @sa hasher + */ +typedef hasher streebog; + +} // namespace digestpp + +#endif // DIGESTPP_ALGORITHM_STREEBOG_HPP \ No newline at end of file diff --git a/ext/include/digestpp/algorithm/whirlpool.hpp b/ext/include/digestpp/algorithm/whirlpool.hpp new file mode 100644 index 0000000..cc6538f --- /dev/null +++ b/ext/include/digestpp/algorithm/whirlpool.hpp @@ -0,0 +1,40 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_ALGORITHM_WHIRLPOOL_HPP +#define DIGESTPP_ALGORITHM_WHIRLPOOL_HPP + +#include "../hasher.hpp" +#include "detail/whirlpool_provider.hpp" + +namespace digestpp +{ + +/** + * @brief Whirlpool hash function + * + * @hash + * + * @outputsize 512 bits + * + * @defaultsize 512 bits + * + * @par Example:\n + * @code // Output a Whirlpool digest of a string + * digestpp::whirlpool hasher; + * hasher.absorb("The quick brown fox jumps over the lazy dog"); + * std::cout << hasher.hexdigest() << '\n'; + * @endcode + * + * @par Example output:\n + * @code b97de512e91e3828b40d2b0fdce9ceb3c4a71f9bea8d88e75c4fa854df36725fd2b52eb6544edcacd6f8beddfea403cb55ae31f03ad62a5ef54e42ee82c3fb35 + * @endcode + * + * @sa hasher + */ +typedef hasher whirlpool; + +} // namespace digestpp + +#endif // DIGESTPP_ALGORITHM_WHIRLPOOL_HPP \ No newline at end of file diff --git a/ext/include/digestpp/detail/absorb_data.hpp b/ext/include/digestpp/detail/absorb_data.hpp new file mode 100644 index 0000000..d697229 --- /dev/null +++ b/ext/include/digestpp/detail/absorb_data.hpp @@ -0,0 +1,46 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_DETAIL_ABSORB_DATA_HPP +#define DIGESTPP_DETAIL_ABSORB_DATA_HPP + +namespace digestpp +{ + +namespace detail +{ + +// Accumulate data and call the transformation function for full blocks. +template +inline void absorb_bytes(const unsigned char* data, size_t len, size_t bs, size_t bschk, + unsigned char* m, size_t& pos, T& total, TF transform) +{ + if (pos && pos + len >= bschk) + { + memcpy(m + pos, data, bs - pos); + transform(m, 1); + len -= bs - pos; + data += bs - pos; + total += bs * 8; + pos = 0; + } + if (len >= bschk) + { + size_t blocks = (len + bs - bschk) / bs; + size_t bytes = blocks * bs; + transform(data, blocks); + len -= bytes; + data += bytes; + total += (bytes)* 8; + } + memcpy(m + pos, data, len); + pos += len; +} + + +} // namespace detail + +} // namespace digestpp + +#endif // DIGESTPP_DETAIL_ABSORB_DATA_HPP \ No newline at end of file diff --git a/ext/include/digestpp/detail/functions.hpp b/ext/include/digestpp/detail/functions.hpp new file mode 100644 index 0000000..1775e5d --- /dev/null +++ b/ext/include/digestpp/detail/functions.hpp @@ -0,0 +1,110 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_DETAIL_FUNCTIONS_HPP +#define DIGESTPP_DETAIL_FUNCTIONS_HPP + +#include + +namespace digestpp +{ +namespace detail +{ + +// Byte-swap a 16-bit unsigned integer. +inline uint16_t byteswap(uint16_t val) +{ + return ((val & 0xff) << 8) | ((val & 0xff00) >> 8); +} + +// Byte-swap a 32-bit unsigned integer. +inline uint32_t byteswap(uint32_t val) +{ + return (((val & 0xff000000) >> 24) | + ((val & 0x00ff0000) >> 8) | + ((val & 0x0000ff00) << 8) | + ((val & 0x000000ff) << 24)); +} + +// Byte-swap a 64-bit unsigned integer. +inline uint64_t byteswap(uint64_t val) +{ + return (((val & 0xff00000000000000ull) >> 56) | + ((val & 0x00ff000000000000ull) >> 40) | + ((val & 0x0000ff0000000000ull) >> 24) | + ((val & 0x000000ff00000000ull) >> 8) | + ((val & 0x00000000ff000000ull) << 8) | + ((val & 0x0000000000ff0000ull) << 24) | + ((val & 0x000000000000ff00ull) << 40) | + ((val & 0x00000000000000ffull) << 56)); +} + +#ifdef __APPLE__ +inline size_t byteswap(size_t val) +{ + switch(sizeof(size_t)) + { + case sizeof(uint16_t): + return (size_t)byteswap((uint16_t)val); + + case sizeof(uint32_t): + return (size_t)byteswap((uint32_t)val); + + case sizeof(uint64_t): + return (size_t)byteswap((uint64_t)val); + } +} +#endif + +// Rotate 32-bit unsigned integer to the right. +inline uint32_t rotate_right(uint32_t x, unsigned n) +{ + return (x >> n) | (x << (32 - n)); +} + +// Rotate 32-bit unsigned integer to the left. +inline uint32_t rotate_left(uint32_t x, unsigned n) +{ + return (x << n) | (x >> (32 - n)); +} + +// Rotate 64-bit unsigned integer to the right. +inline uint64_t rotate_right(uint64_t x, unsigned n) +{ + return (x >> n) | (x << (64 - n)); +} + +// Rotate 64-bit unsigned integer to the left. +inline uint64_t rotate_left(uint64_t x, unsigned n) +{ + return (x << n) | (x >> (64 - n)); +} + +// Clear memory, suppressing compiler optimizations. +inline void zero_memory(void *v, size_t n) { + volatile unsigned char *p = static_cast(v); + while (n--) { + *p++ = 0; + } +} + +// Clear memory occupied by an array, suppressing compiler optimizations. +template +inline void zero_memory(std::array& ar) +{ + zero_memory(ar.data(), ar.size() * sizeof(T)); +} + +// Clear memory occupied by std::string +inline void zero_memory(std::string& s) +{ + if (!s.empty()) + zero_memory(&s[0], s.size()); +} + + +} // namespace detail +} // namespace digestpp + +#endif diff --git a/ext/include/digestpp/detail/stream_width_fixer.hpp b/ext/include/digestpp/detail/stream_width_fixer.hpp new file mode 100644 index 0000000..5e0c606 --- /dev/null +++ b/ext/include/digestpp/detail/stream_width_fixer.hpp @@ -0,0 +1,30 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_DETAIL_WIDTH_FIXER_HPP +#define DIGESTPP_DETAIL_WIDTH_FIXER_HPP + +namespace digestpp +{ +namespace detail +{ + +template +struct stream_width_fixer +{ + stream_width_fixer(T value) : v(value) {} + T v; +}; + +template +std::ostream& operator<<(std::ostream& ostr, const stream_width_fixer& value) +{ + return ostr << std::setw(N) << value.v; +} + + +} // namespace detail +} // namespace digestpp + +#endif // DIGESTPP_DETAIL_WIDTH_FIXER_HPP \ No newline at end of file diff --git a/ext/include/digestpp/detail/traits.hpp b/ext/include/digestpp/detail/traits.hpp new file mode 100644 index 0000000..34bbd69 --- /dev/null +++ b/ext/include/digestpp/detail/traits.hpp @@ -0,0 +1,35 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_DETAIL_TRAITS_HPP +#define DIGESTPP_DETAIL_TRAITS_HPP + +#include // needed for testing std::byte + +namespace digestpp +{ +namespace detail +{ + +template +struct is_xof +{ + static const bool value = T::is_xof; +}; + +template +struct is_byte +{ + static const bool value = std::is_same::value || + std::is_same::value || +#if (defined(_HAS_STD_BYTE) && _HAS_STD_BYTE) || (defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603) + std::is_same::value || +#endif + std::is_same::value; +}; + +} // namespace detail +} // namespace digestpp + +#endif // DIGESTPP_DETAIL_TRAITS_HPP \ No newline at end of file diff --git a/ext/include/digestpp/detail/validate_hash_size.hpp b/ext/include/digestpp/detail/validate_hash_size.hpp new file mode 100644 index 0000000..51bbbde --- /dev/null +++ b/ext/include/digestpp/detail/validate_hash_size.hpp @@ -0,0 +1,41 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_DETAIL_VALIDATE_HASH_SIZE_HPP +#define DIGESTPP_DETAIL_VALIDATE_HASH_SIZE_HPP + +namespace digestpp +{ +namespace detail +{ + +// Validate that variable hash is within the list of allowed sizes +inline void validate_hash_size(size_t hs, std::initializer_list set) +{ + if (!hs) + throw std::runtime_error("hash size can't be zero"); + + if (std::find(set.begin(), set.end(), hs)) + return; + + throw std::runtime_error("invalid hash size"); +} + +// Validate variable hash size up to max bits +inline void validate_hash_size(size_t hs, size_t max) +{ + if (!hs) + throw std::runtime_error("hash size can't be zero"); + + if (hs % 8) + throw std::runtime_error("non-byte hash sizes are not supported"); + + if (hs > max) + throw std::runtime_error("invalid hash size"); +} + +} // namespace detail +} // namespace digestpp + +#endif // DIGESTPP_DETAIL_VALIDATE_HASH_SIZE_HPP \ No newline at end of file diff --git a/ext/include/digestpp/digestpp.hpp b/ext/include/digestpp/digestpp.hpp new file mode 100644 index 0000000..c0d178f --- /dev/null +++ b/ext/include/digestpp/digestpp.hpp @@ -0,0 +1,24 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#include "hasher.hpp" +#include "algorithm/sha2.hpp" +#include "algorithm/sha3.hpp" +#include "algorithm/shake.hpp" +#include "algorithm/skein.hpp" +#include "algorithm/blake.hpp" +#include "algorithm/blake2.hpp" +#include "algorithm/groestl.hpp" +#include "algorithm/jh.hpp" +#include "algorithm/md5.hpp" +#include "algorithm/sha1.hpp" +#include "algorithm/sm3.hpp" +#include "algorithm/streebog.hpp" +#include "algorithm/whirlpool.hpp" +#include "algorithm/k12m14.hpp" +#include "algorithm/kupyna.hpp" +#include "algorithm/kmac.hpp" +#include "algorithm/esch.hpp" +#include "algorithm/echo.hpp" + diff --git a/ext/include/digestpp/hasher.hpp b/ext/include/digestpp/hasher.hpp new file mode 100644 index 0000000..b75d6bb --- /dev/null +++ b/ext/include/digestpp/hasher.hpp @@ -0,0 +1,344 @@ +/* +This code is written by kerukuro and released into public domain. +*/ + +#ifndef DIGESTPP_HASHER_HPP +#define DIGESTPP_HASHER_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "detail/traits.hpp" +#include "detail/stream_width_fixer.hpp" +#include "algorithm/mixin/null_mixin.hpp" + +namespace digestpp +{ + +/** + * \brief Main class template implementing the public API for hashing + * + * Individual hash functions are defined by typedefs. + * See \ref digestpp namespace description for description of supported hash functions with usage examples. + * + * \param HashProvider A class implementing the algorithm via traditional init/update/final interface. + * \param Mixin A class template which can be used to inject additional functions to the public API of the hasher. + * + * \sa digestpp + */ +template class Mixin = mixin::null_mixin> +class hasher : public Mixin +{ + public: + + /** + * \brief Default constructor + * + * \available_if * HashProvider is a hash function with fixed output size, OR + * * HashProvider is a hash function with sensible default output size, OR + * * HashProvider is an extendable output function (XOF) + */ + template::value>::type* = nullptr> + hasher() + { + provider.init(); + } + + /** + * \brief Constructor with hash size parameter + * + * Supported output sizes for each algorithm are listed in the description of corresponding typedef. + * + * \available_if * HashProvider supports multiple output sizes, AND + * * HashProvider is not an extendable output function (XOF) + * + * \param[in] hashsize Desired output digest size (in bits). + * \throw std::runtime_error if the requested output size is not supported by the algorithm. + */ + template::value>::type* = nullptr> + hasher(size_t hashsize) : provider(hashsize) + { + provider.init(); + } + + /** + * \brief Absorbs bytes from a C-style pointer to character buffer + * \param[in] data Pointer to data to absorb + * \param[in] len Size of data to absorb (in bytes) + * \return Reference to *this + * + * @par Example:\n + * @code // Calculate SHA-512/256 digest of a C array and output it in hex format + * unsigned char c[32]; + * std::iota(c, c + sizeof(c), 0); + * cout << digestpp::sha512(256).absorb(c, sizeof(c)).hexdigest() << std::endl; + * @endcode + */ + template::value>::type* = nullptr> + inline hasher& absorb(const T* data, size_t len) + { + provider.update(reinterpret_cast(data), len); + return *this; + } + + /** + * \brief Absorbs bytes from std::basic_string + * \param[in] str String to absorb + * \return Reference to *this + */ + template::value && !std::is_same::value>::type* = nullptr> + inline hasher& absorb(const std::basic_string& str) + { + if (!str.empty()) + provider.update(reinterpret_cast(&str[0]), str.size()); + return *this; + } + + /** + * \brief Absorbs bytes from std::string + * \param[in] str String to absorb + * \return Reference to *this + * @par Example:\n + * @code // Calculate BLAKE2b-256 digest from an std::string and output it in hex format + * std::string str = "The quick brown fox jumps over the lazy dog"; + * std::cout << digestpp::blake2b(256).absorb(str).hexdigest() << std::endl; + * @endcode + */ + inline hasher& absorb(const std::string& str) + { + if (!str.empty()) + provider.update(reinterpret_cast(&str[0]), str.size()); + return *this; + } + + /** + * \brief Absorbs bytes from std::istream + * \param[in] istr Stream to absorb + * \return Reference to *this + * @par Example:\n + * @code // Calculate SHA-256 digest of a file and output it in hex format + * std::ifstream file("filename", std::ios_base::in|std::ios_base::binary); + * std::cout << digestpp::sha256().absorb(file).hexdigest() << std::endl; + * @endcode + */ + template::value>::type* = nullptr> + inline hasher& absorb(std::basic_istream& istr) + { + const int tmp_buffer_size = 10000; + unsigned char buffer[tmp_buffer_size]; + while (istr.read(reinterpret_cast(buffer), sizeof(buffer))) + { + provider.update(buffer, sizeof(buffer)); + } + size_t gcount = istr.gcount(); + if (gcount) + { + provider.update(buffer, gcount); + } + return *this; + } + + /** + * \brief Absorbs bytes from an iterator sequence + * \param[in] begin Begin iterator + * \param[in] end End iterator + * \return Reference to *this + * + * @par Example:\n + * @code // Calculate SHA-512 digest of a vector and output it in hex format + * std::vector v(100); + * std::iota(v.begin(), v.end(), 0); + * std::cout << digestpp::sha512().absorb(v.begin(), v.end()).hexdigest() << std::endl; + * @endcode + */ + template + inline hasher& absorb(IT begin, IT end) + { + while (begin != end) + { + unsigned char byte = *begin++; + provider.update(&byte, 1); + } + return *this; + } + + /** + * \brief Squeeze bytes into user-provided preallocated buffer. + * + * After each invocation of this function the internal state of the hasher changes + * so that the next call will generate different (additional) output bytes. + * To reset the state and start new digest calculation, use \ref reset function. + * + * \available_if HashProvider is an extendable output function (XOF) + * + * \param[out] buf Buffer to squeeze data to; must be of byte type (char, unsigned char or signed char) + * \param[in] len Size of data to squeeze (in bytes) + */ + template::value && detail::is_xof::value>::type* = nullptr> + inline void squeeze(T* buf, size_t len) + { + provider.squeeze(reinterpret_cast(buf), len); + } + + /** + * \brief Squeeze bytes into an output iterator. + * + * After each invocation of this function the internal state of the hasher changes + * so that the next call will generate different (additional) output bytes. + * To reset the state and start new digest calculation, use \ref reset function. + * + * \available_if HashProvider is an extendable output function (XOF) + * + * \param[in] len Size of data to squeeze (in bytes) + * \param[out] it output iterator to a byte container + * @par Example:\n + * @code // Generate long output using SHAKE-256 extendable output function using multiple calls to squeeze() + * std::vector v; + * digestpp::shake256 xof; + * xof.absorb("The quick brown fox jumps over the lazy dog"); + * xof.squeeze(1000, back_inserter(v)); + * xof.squeeze(1000, back_inserter(v)); + * xof.squeeze(1000, back_inserter(v)); + * std::cout << "Squeezed " << v.size() << " bytes." << std::endl; + * @endcode + */ + template::value>::type* = nullptr> + inline void squeeze(size_t len, OI it) + { + std::vector hash(len); + provider.squeeze(&hash[0], len); + std::copy(hash.begin(), hash.end(), it); + } + + /** + * \brief Squeeze bytes and return them as a hex string. + * + * After each invocation of this function the internal state of the hasher changes + * so that the next call will generate different (additional) output bytes. + * To reset the state and start new digest calculation, use \ref reset function. + * + * \available_if HashProvider is an extendable output function (XOF) + * + * \param[in] len Size of data to squeeze (in bytes) + * \return Calculated digest as a hexademical string + * @par Example:\n + * @code // Generate 64-byte digest using customizable cSHAKE-256 algorithm and print it in hex format + * digestpp::cshake256 xof; + * xof.set_customization("My Customization"); + * std::cout << xof.absorb("The quick brown fox jumps over the lazy dog").hexsqueeze(64) << std::endl; + * @endcode + */ + template::value>::type* = nullptr> + inline std::string hexsqueeze(size_t len) + { + std::ostringstream res; + res << std::setfill('0') << std::hex; + squeeze(len, std::ostream_iterator>(res, "")); + return res.str(); + } + + /** + * \brief Output binary digest into user-provided preallocated buffer. + * + * This function does not change the state of the hasher and can be called multiple times, producing the same result. + * To reset the state and start new digest calculation, use \ref reset function. + * + * \available_if HashProvider is a hash function (not XOF) + * + * \param[out] buf Buffer to squeeze data to; must be of byte type (char, unsigned char or signed char) + * \param[in] len Size of the buffer + * \throw std::runtime_error if the buffer size is not enough to fit the calculated digest + * (fixed by the algorithm or specified in the hasher constructor). + * @par Example:\n + * @code // Output binary digest to a raw C array + * unsigned char buf[32]; + * digestpp::sha3(256).absorb("The quick brown fox jumps over the lazy dog").digest(buf, sizeof(buf)); + * @endcode + */ + template::value && !detail::is_xof::value>::type* = nullptr> + inline void digest(T* buf, size_t len) const + { + if (len < provider.hash_size() / 8) + throw std::runtime_error("Invalid buffer size"); + + HashProvider copy(provider); + copy.final(buf); + } + + /** + * \brief Write binary digest into an output iterator. + * + * This function does not change the state of the hasher and can be called multiple times, producing the same result. + * To reset the state and start new digest calculation, use \ref reset function. + * + * \available_if HashProvider is a hash function (not XOF) + * + * \param[out] it Output iterator to a byte container. + * @par Example:\n + * @code // Output binary SHA3-256 digest to a vector + * vector v; + * digestpp::sha3(256).absorb("The quick brown fox jumps over the lazy dog").digest(back_inserter(v)); + * @endcode + */ + template::value>::type* = nullptr> + inline void digest(OI it) const + { + HashProvider copy(provider); + std::vector hash(provider.hash_size() / 8); + copy.final(&hash[0]); + std::copy(hash.begin(), hash.end(), it); + } + + /** + * \brief Return hex digest of absorbed data. + * + * This function does not change the state of the hasher and can be called multiple times, producing the same result. + * To reset the state and start new digest calculation, use \ref reset function. + * + * \available_if HashProvider is a hash function (not XOF) + * + * \return Calculated digest as a hexademical string + * @par Example:\n + * @code // Calculate BLAKE2b digest from a double quoted string and output it in hex format + * std::cout << digestpp::blake2b().absorb("The quick brown fox jumps over the lazy dog").hexdigest() << std::endl; + * @endcode + */ + template::value>::type* = nullptr> + inline std::string hexdigest() const + { + std::ostringstream res; + res << std::setfill('0') << std::hex; + digest(std::ostream_iterator>(res, "")); + return res.str(); + } + + /** + * \brief Reset the hasher state to start new digest computation. + * + * \param[in] resetParameters if true, also clear optional parameters (personalization, salt, etc) + */ + inline void reset(bool resetParameters = false) + { + if (resetParameters) + provider.clear(); + provider.init(); + } + +private: + friend Mixin; + HashProvider provider; +}; + + +} // namespace digestpp + +#endif // DIGESTPP_HASHER_HPP \ No newline at end of file diff --git a/infrastructure/Dockerfile b/infrastructure/Dockerfile new file mode 100644 index 0000000..aeeba00 --- /dev/null +++ b/infrastructure/Dockerfile @@ -0,0 +1,7 @@ +FROM postgres:latest + +ENV POSTGRES_DB=password_keeper +ENV POSTGRES_USER=user +ENV POSTGRES_PASSWORD=temp + +COPY SQL_Scripts/users.sql /docker-entrypoint-initdb.d/ \ No newline at end of file diff --git a/infrastructure/SQL_Scripts/users.sql b/infrastructure/SQL_Scripts/users.sql new file mode 100644 index 0000000..570ce88 --- /dev/null +++ b/infrastructure/SQL_Scripts/users.sql @@ -0,0 +1,6 @@ +CREATE TABLE IF NOT EXISTS users ( + id SERIAL PRIMARY KEY, + username VARCHAR(50) UNIQUE NOT NULL, + passwordSalt VARCHAR(150) NOT NULL, + passwordHash VARCHAR(150) NOT NULL +); \ No newline at end of file diff --git a/infrastructure/compose.yaml b/infrastructure/compose.yaml index e8c67a6..9ae1909 100644 --- a/infrastructure/compose.yaml +++ b/infrastructure/compose.yaml @@ -1,7 +1,8 @@ -version: '3.8' services: db: - image: postgres:latest + build: + context: . + dockerfile: Dockerfile restart: always environment: POSTGRES_DB: password_keeper diff --git a/launcher.command b/launcher.command index 31cc8e6..2a1922f 100755 --- a/launcher.command +++ b/launcher.command @@ -1,2 +1,2 @@ #!/bin/sh -cd "$(dirname "${0}")" && ./oop +cd "$(dirname "${0}")" && ./Password-Keeper-src diff --git a/main.cpp b/main.cpp deleted file mode 100644 index 844063e..0000000 --- a/main.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include -#include -#include - -int main() { - pqxx::connection c{"dbname=password_keeper user=user password=temp host=localhost port=5433"}; - std::cout<<"Connection secured"; - return 0; -} diff --git a/scripts/cmake.sh b/scripts/cmake.sh index 63c11e0..a6d73eb 100755 --- a/scripts/cmake.sh +++ b/scripts/cmake.sh @@ -42,7 +42,8 @@ configure() { cmake -S "${SOURCE_DIR}" \ -B "${BUILD_DIR}" \ -DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \ - -DCMAKE_INSTALL_PREFIX="${INSTALL_DIR}" \ + -DCMAKE_INSTALL_PREFIX="${INSTALL_DIR}"\ + -DSKIP_BUILD_TEST=ON\ "${CMAKE_OPTS[@]}" } diff --git a/scripts/run_cppcheck.sh b/scripts/run_cppcheck.sh index 7c75cca..d008ace 100755 --- a/scripts/run_cppcheck.sh +++ b/scripts/run_cppcheck.sh @@ -9,4 +9,5 @@ cppcheck --enable=all \ --suppress=missingIncludeSystem \ --suppress=unmatchedSuppression \ --suppress=useStlAlgorithm \ + --suppress=unusedFunction \ --error-exitcode=1 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..f7eb4ed --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,50 @@ +cmake_minimum_required(VERSION 3.26) + +project(Password-Keeper-src) +set(SRC_PROJECT ${PROJECT_NAME} PARENT_SCOPE) + +add_library(${PROJECT_NAME}_lib + Database/Database.cpp + EnvironmentReader/EnvironmentReader.cpp + User/User.cpp + Utils/PasswordHash.cpp + Database/Auth.cpp + Utils/EnvVarManager.cpp + Logger/Logger.cpp +) + +target_include_directories(${PROJECT_NAME}_lib SYSTEM PRIVATE + ${pqxx_SOURCE_DIR}/include +) + +target_include_directories(${PROJECT_NAME}_lib SYSTEM PUBLIC + ../ext/include/digestpp +) + +target_include_directories(${PROJECT_NAME}_lib PUBLIC + Database + EnvironmentReader + User + Utils + Logger +) + +target_link_directories(${PROJECT_NAME}_lib PUBLIC ${pqxx_SOURCE_DIR}/lib) +target_link_libraries(${PROJECT_NAME}_lib PUBLIC pqxx) + +add_executable(${PROJECT_NAME} + main.cpp +) +target_link_libraries(${PROJECT_NAME} PRIVATE ${PROJECT_NAME}_lib) + +include(${CMAKE_HELPER_DIR}/CompilerFlags.cmake) + +install(TARGETS ${PROJECT_NAME} DESTINATION ${DESTINATION_DIR}) +if (APPLE) + install(FILES ${PROJECT_ROOT}/launcher.command DESTINATION ${DESTINATION_DIR}) +endif () + +copy_files(FILES tastatura.txt) +if (EXISTS ${PROJECT_ROOT}/.env) + copy_files(FILES .env) +endif () diff --git a/src/Database/Auth.cpp b/src/Database/Auth.cpp new file mode 100644 index 0000000..85fca37 --- /dev/null +++ b/src/Database/Auth.cpp @@ -0,0 +1,39 @@ +#include "Auth.h" + +#include +#include + +Auth::Auth(std::string username, std::string password) + : username(std::move(username)), password(std::move(password)) { +} + +User Auth::createAccount() const { + try { + auto currentUser = User(username, password); + database.createAccount(currentUser); + currentUser.setUserId(database.getCurrentUserId(currentUser.getUsername())); + return currentUser; + } + catch (pqxx::unique_violation&) { + throw ; + } + catch (std::exception&) { + throw; + } +} + +User Auth::login() const { + try { + auto [storedPasswordSalt, storedPasswordHash] = database.getLoginInformation(username); + if (const auto hashedInputPassword = PasswordHash(password, storedPasswordSalt); + hashedInputPassword.getPasswordHash() == storedPasswordHash) { + auto currentUser = User(username, hashedInputPassword); + currentUser.setUserId(database.getCurrentUserId(currentUser.getUsername())); + + return currentUser; + } + throw std::invalid_argument("Wrong password"); + } catch (std::exception&) { + throw; + } +} diff --git a/src/Database/Auth.h b/src/Database/Auth.h new file mode 100644 index 0000000..2934f05 --- /dev/null +++ b/src/Database/Auth.h @@ -0,0 +1,20 @@ +#ifndef AUTH_H +#define AUTH_H +#include "Database.h" +#include "../User/User.h" + +class Auth { + Database &database = Database::getDatabaseInstance(); + std::string username; + std::string password; + +public: + explicit Auth(std::string, std::string); + + [[nodiscard]] User createAccount() const; + + [[nodiscard]] User login() const; +}; + + +#endif //AUTH_H diff --git a/src/Database/Database.cpp b/src/Database/Database.cpp new file mode 100644 index 0000000..290af99 --- /dev/null +++ b/src/Database/Database.cpp @@ -0,0 +1,115 @@ +#include "Database.h" + +#include + +std::string Database::connString; + +Database::Database() { + try { + connection = std::make_unique(connString); + if (!connection->is_open()) { + throw std::runtime_error("Database exists but a connection couldn't be established"); + } + } catch (const std::exception &) { + connection = nullptr; + throw ; + } +} + +Database::~Database() { + if (connection) { + connection->close(); + } + connection = nullptr; +} + +Database &Database::getDatabaseInstance() { + static Database databaseInstance; + return databaseInstance; +} + +void Database::setConnString(const std::string &connectionString) { + connString = connectionString; +} + +void Database::createAccount(const User ¤tUser) const { + pqxx::work work(*connection); + try { + work.exec_params("INSERT INTO users (username, passwordSalt, passwordHash)" + " VALUES ($1, $2, $3)", + currentUser.getUsername(), + currentUser.getPasswordSalt(), + currentUser.getPasswordHash() + ); + work.commit(); + } + catch (const pqxx::unique_violation& e) { + std::cerr << e.what() << std::endl; + throw; + } + catch (const std::exception &e) { + std::cerr << "Exception: " << e.what() << std::endl; + throw; + } +} + +std::tuple Database::getLoginInformation(const std::string &username) const { + pqxx::work work(*connection); + try { + const auto queryResult = work.exec_params("SELECT passwordSalt, passwordHash" + " FROM users WHERE username = $1", username); + if (queryResult.empty()) { + throw std::runtime_error("User not found"); + } + auto passwordSalt = queryResult[0][0].as(); + auto passwordHash = queryResult[0][1].as(); + return {passwordSalt, passwordHash}; + } catch (const std::exception &e) { + std::cerr << "Exception: " << e.what() << std::endl; + throw; + } +} + +int Database::getCurrentUserId(const std::string &username) const { + pqxx::work work(*connection); + try { + const auto queryResult = work.exec_params("SELECT id FROM users WHERE username = $1", + username); + if (queryResult.empty()) + throw std::runtime_error("User not found"); + return queryResult[0][0].as(); + } catch (const std::exception &e) { + std::cerr << "Exception: " << e.what() << std::endl; + throw; + } +} + +int Database::getNumberOfUsers() const { + pqxx::work work(*connection); + try { + const auto queryResult = work.exec_params("SELECT COUNT(*) FROM users"); + return queryResult[0][0].as(); + } + catch (const std::exception &e) { + std::cerr << "Exception: " << e.what() << std::endl; + throw; + } +} + +User Database::getUserByUsername(std::string &username) const { + pqxx::work work(*connection); + try { + const auto queryResult = work.exec_params("SELECT id, username, passwordSalt, passwordHash FROM users" + " WHERE username = $1", username); + const int _userId = queryResult[0][0].as(); + const auto _username = queryResult[0][1].as(); + const auto _passwordSalt = queryResult[0][2].as(); + const auto _passwordHash = queryResult[0][3].as(); + return {_userId, _username, _passwordHash, + _passwordSalt}; + } + catch (const std::exception &e) { + std::cerr << "Exception: " << e.what() << std::endl; + throw; + } +} diff --git a/src/Database/Database.h b/src/Database/Database.h new file mode 100644 index 0000000..17f648e --- /dev/null +++ b/src/Database/Database.h @@ -0,0 +1,40 @@ +#ifndef DATABASE_H +#define DATABASE_H + +#include +#include "../User/User.h" + +class Database { + std::unique_ptr connection; + static std::string connString; + + Database(); + + ~Database(); + +public: + Database(const Database &) = delete; + + Database &operator=(const Database &) = delete; + + Database(Database &&) = delete; + + Database &operator=(Database &&) = delete; + + [[nodiscard]] std::tuple getLoginInformation(const std::string &) const; + + static Database &getDatabaseInstance(); + + static void setConnString(const std::string &); + + void createAccount(const User& currentUser) const; + + [[nodiscard]] int getCurrentUserId(const std::string&) const; + + [[nodiscard]] int getNumberOfUsers() const; + + User getUserByUsername(std::string &username) const; +}; + + +#endif //DATABASE_H \ No newline at end of file diff --git a/src/EnvironmentReader/EnvironmentReader.cpp b/src/EnvironmentReader/EnvironmentReader.cpp new file mode 100644 index 0000000..1ad02a6 --- /dev/null +++ b/src/EnvironmentReader/EnvironmentReader.cpp @@ -0,0 +1,61 @@ +#include "EnvironmentReader.h" +#include +#include "../Database/Database.h" +#include "../Utils/EnvVarManager.h" +#include +#include + +#include "../Logger/Logger.h" + +EnvironmentReader::EnvironmentReader() { + std::ifstream file(filePath); + std::string line; + while (std::getline(file, line)) { + if (line.empty()) continue; + auto delimiterPos = line.find('='); + line.erase(line.end() - 1); + if (delimiterPos != std::string::npos) { + std::string key = line.substr(0, delimiterPos); + std::string value = line.substr(delimiterPos + 1); + EnvVarManager::set(key,value); + } + } +} + +EnvironmentReader& EnvironmentReader::getEnvReader() { + static EnvironmentReader envReader; + return envReader; +} + +std::string EnvironmentReader::getConnString() { + auto &logger = Logger::getInstance(); + if (EnvVarManager::get("DB_HOST").empty()) { + logger.log(LogLevel::LOG_ERROR, "DB_HOST not set"); + throw std::invalid_argument("Environment variable DB_HOST is not set"); + } + if (EnvVarManager::get("DB_NAME").empty()) { + logger.log(LogLevel::LOG_ERROR, "DB_NAME not set"); + throw std::invalid_argument("Environment variable DB_NAME is not set"); + } + if (EnvVarManager::get("DB_USER").empty()) { + logger.log(LogLevel::LOG_ERROR, "DB_USER not set"); + throw std::invalid_argument("Environment variable DB_USER is not set"); + } + if (EnvVarManager::get("DB_PASSWORD").empty()) { + logger.log(LogLevel::LOG_ERROR, "DB_PASSWORD not set"); + throw std::invalid_argument( + "Environment variable DB_PASSWORD is not set"); + } + if (EnvVarManager::get("DB_PORT").empty()) { + logger.log(LogLevel::LOG_ERROR, "DB_PORT not set"); + throw std::invalid_argument("Environment variable DB_PORT is not set"); + } + + std::string connString = + "dbname=" + EnvVarManager::get("DB_NAME") + " user=" + + EnvVarManager::get("DB_USER") + + " password=" + EnvVarManager::get("DB_PASSWORD") + " host=" + + EnvVarManager::get("DB_HOST") + " port=" + EnvVarManager::get("DB_PORT"); + logger.log(LogLevel::INFO, "Connection string set"); + return connString; +} diff --git a/src/EnvironmentReader/EnvironmentReader.h b/src/EnvironmentReader/EnvironmentReader.h new file mode 100644 index 0000000..5913fc5 --- /dev/null +++ b/src/EnvironmentReader/EnvironmentReader.h @@ -0,0 +1,26 @@ +#ifndef ENVIRONMENTREADER_H +#define ENVIRONMENTREADER_H + +#include + +class EnvironmentReader { + std::string filePath = ".env"; + + EnvironmentReader(); + +public: + EnvironmentReader(const EnvironmentReader &) = delete; + + EnvironmentReader &operator=(const EnvironmentReader &) = delete; + + EnvironmentReader(EnvironmentReader &&) = delete; + + EnvironmentReader &operator=(EnvironmentReader &&) = delete; + + static EnvironmentReader &getEnvReader(); + + static std::string getConnString(); +}; + + +#endif //ENVIRONMENTREADER_H diff --git a/src/Logger/Logger.cpp b/src/Logger/Logger.cpp new file mode 100644 index 0000000..332e80a --- /dev/null +++ b/src/Logger/Logger.cpp @@ -0,0 +1,87 @@ +#include "Logger.h" + +#include +#include +#include +#include +std::unique_ptr Logger::instance = nullptr; +std::once_flag Logger::initFlag; + +void Logger::create(const std::string &folderName) { + std::call_once(initFlag, [&folderName]() { + instance.reset(new Logger(folderName)); + }); +} + +Logger &Logger::getInstance() { + if (!instance) { + throw std::runtime_error( + "Logger::create() must be called before getInstance()"); + } + return *instance; +} + +Logger::Logger(std::string folderName): folderName(std::move(folderName)), done(false) { + const auto currentPath = std::filesystem::current_path() / std::filesystem::path(this->folderName); + + create_directory(currentPath); + + const auto filePath = currentPath.string() / std::filesystem::path(generateTimestampedFilename()); + + logFile.open(filePath, std::ios::out | std::ios::app); + loggingThread = std::thread(&Logger::processEntries, this); +} + +Logger::~Logger() { + if (loggingThread.joinable()) { + { + std::lock_guard lock(mutex); + done = true; + } + condVar.notify_all(); + loggingThread.join(); + } + if (logFile.is_open()) { + logFile.close(); + } +} + +void Logger::log(const LogLevel logLevel, const std::string &message) { + std::string levelStr; + switch (logLevel) { + case LogLevel::INFO: levelStr = "[INFO]"; + break; + case LogLevel::WARNING: levelStr = "[WARNING]"; + break; + case LogLevel::LOG_ERROR: levelStr = "[ERROR]"; + break; + default: levelStr = "[INFO]"; + break; + } + const std::string fullMessage = levelStr + " " + message; + std::lock_guard lock(mutex); + logQueue.push(fullMessage); + condVar.notify_one(); +} + +void Logger::processEntries() { + while (true) { + std::unique_lock lock(mutex); + condVar.wait(lock, [this] { return !logQueue.empty() || done; }); + while (!logQueue.empty()) { + logFile << logQueue.front() << std::endl; + logQueue.pop(); + } + if (done) break; + } +} + +std::string Logger::generateTimestampedFilename() { + const auto now = std::chrono::system_clock::now(); + const auto time = std::chrono::system_clock::to_time_t(now); + std::ostringstream oss; + oss << "log_" + << std::put_time(std::localtime(&time), "%Y%m%d_%H%M%S") + << ".log"; + return oss.str(); +} diff --git a/src/Logger/Logger.h b/src/Logger/Logger.h new file mode 100644 index 0000000..6f5883a --- /dev/null +++ b/src/Logger/Logger.h @@ -0,0 +1,61 @@ +#ifndef LOGGER_H +#define LOGGER_H +#include +#include +#include +#include +#include +#include + +enum class LogLevel { + INFO, + WARNING, + LOG_ERROR +}; + + +class Logger { + struct Deleter { + void operator()(const Logger *logger) const { + delete logger; + } + }; + + std::string folderName; + std::ofstream logFile; + std::queue logQueue; + std::mutex mutex; + std::condition_variable condVar; + std::thread loggingThread; + std::atomic done; + + static std::unique_ptr instance; + static std::once_flag initFlag; + + explicit Logger(std::string); + + void processEntries(); + + static std::string generateTimestampedFilename() ; + +protected: + ~Logger(); + +public: + static void create(const std::string &); + + static Logger &getInstance(); + + Logger(const Logger &) = delete; + + Logger &operator=(const Logger &) = delete; + + Logger(Logger &&) = delete; + + Logger &operator=(Logger &&) = delete; + + void log(LogLevel, const std::string &); +}; + + +#endif //LOGGER_H diff --git a/src/User/User.cpp b/src/User/User.cpp new file mode 100644 index 0000000..21e6f67 --- /dev/null +++ b/src/User/User.cpp @@ -0,0 +1,49 @@ +#include "User.h" + +#include +#include + +#include "../Logger/Logger.h" + +std::ostream &operator<<(std::ostream &os, const User &user) { + os << "UserId:" << user.userId << '\n' << + " username: " << user.username << '\n' << + "password: " << user.passwordHash << '\n'; + return os; +} + +User::User(std::string username, const std::string &password) + : username(std::move(username)), passwordHash(password), userId(-1) { +} + +User::User(std::string username, PasswordHash passwordHash) + : username(std::move(username)), passwordHash(std::move(passwordHash)), userId(-1) { +} + +User::User(const int userId, std::string username, const std::string &passwordHash, std::string passwordSalt) + : username(std::move(username)), passwordHash(passwordHash, std::move(passwordSalt), false), userId(userId) {} + +bool User::operator==(const User &other) const { + return this->username == other.username && this->userId == other.userId && this->passwordHash == other.passwordHash; +} + +std::string User::getUsername() const { + return this->username; +} + +std::string User::getPasswordHash() const { + return this->passwordHash.getPasswordHash(); +} + +std::string User::getPasswordSalt() const { + return this->passwordHash.getPasswordSalt(); +} + +int User::getUserId() const { + return this->userId; +} + +void User::setUserId(const int id) { + this->userId = id; +} + diff --git a/src/User/User.h b/src/User/User.h new file mode 100644 index 0000000..c489132 --- /dev/null +++ b/src/User/User.h @@ -0,0 +1,26 @@ +#ifndef USER_H +#define USER_H +#include + +#include "../Utils/PasswordHash.h" + + +class User { + std::string username; + PasswordHash passwordHash; + int userId; +public: + User(std::string, const std::string&); + User(std::string, PasswordHash); + User(int, std::string, const std::string &, std::string); + bool operator==(const User &) const; + friend std::ostream& operator<<(std::ostream& os, const User& user); + [[nodiscard]] std::string getUsername() const; + [[nodiscard]] std::string getPasswordHash() const; + [[nodiscard]] std::string getPasswordSalt() const; + [[nodiscard]] int getUserId() const; + void setUserId(int); +}; + + +#endif //USER_H diff --git a/src/Utils/EnvVarManager.cpp b/src/Utils/EnvVarManager.cpp new file mode 100644 index 0000000..e89f054 --- /dev/null +++ b/src/Utils/EnvVarManager.cpp @@ -0,0 +1,39 @@ +#include "EnvVarManager.h" +#include +std::string EnvVarManager::get(const std::string & varKey) { + return getEnv(varKey); +} + +int EnvVarManager::set(const std::string & varKey, const std::string & varValue) { + return setEnv(varKey, varValue); +} + +int EnvVarManager::unset(const std::string & varKey) { + return unsetEnv(varKey); +} + +std::string EnvVarManager::getEnv(const std::string & varKey) { + const char* value = getenv(varKey.c_str()); + return value ? std::string(value) : ""; +} + +int EnvVarManager::setEnv(const std::string & varKey, const std::string & varValue) { +#if defined(_WIN32) || defined(_WIN64) + return SetEnvironmentVariable(varKey.c_str(), varValue.c_str()) != 0; +#else + return setenv(varKey.c_str(), varValue.c_str(), 1) == 0; +#endif +} + +int EnvVarManager::unsetEnv(const std::string & varKey) { +#if defined(_WIN32) || defined(_WIN64) + return SetEnvironmentVariable(varKey.c_str(), NULL) != 0; +#else + return unsetenv(varKey.c_str()) == 0; +#endif +} + +std::ostream & operator<<(std::ostream & os, const EnvVarManager& envVarManager) { + os<<"EnvVarManager\n"< +#endif +#include + +class EnvVarManager { + static std::string getEnv(const std::string&); + static int setEnv(const std::string&, const std::string&); + static int unsetEnv(const std::string&); +public: + static std::string get(const std::string&); + static int set(const std::string&, const std::string&); + static int unset(const std::string&); + friend std::ostream& operator<<(std::ofstream&, EnvVarManager&); +}; + + + +#endif //ENVVARMANAGER_H diff --git a/src/Utils/PasswordHash.cpp b/src/Utils/PasswordHash.cpp new file mode 100644 index 0000000..6ca802d --- /dev/null +++ b/src/Utils/PasswordHash.cpp @@ -0,0 +1,55 @@ +#include "PasswordHash.h" + +#include +#include +#include +#include + +PasswordHash::PasswordHash(const std::string &password) + : salt(generateSalt()) { + hashedPassword = hashPasswordWithSalt(password); +} + +bool PasswordHash::operator==(const PasswordHash & other) const { + return this->hashedPassword == other.hashedPassword && this->salt == other.salt; +} + +PasswordHash::PasswordHash(const std::string &password, std::string passwordSalt, const bool generateHash) + : salt(std::move(passwordSalt)) { + if(generateHash) + hashedPassword = hashPasswordWithSalt(password); + else hashedPassword = password; +} + +std::ostream &operator<<(std::ostream &os, const PasswordHash &hashedPassword) { + os << hashedPassword.salt << hashedPassword.hashedPassword; + return os; +} + +std::string PasswordHash::generateSalt() { + std::random_device rd; + std::mt19937 generator(rd()); + std::uniform_int_distribution distribution(0, 255); + + std::string salt; + for (size_t i = 0; i < 16; ++i) { + const auto byte = static_cast(distribution(generator)); + salt += "0123456789abcdef"[byte >> 4]; + salt += "0123456789abcdef"[byte & 0x0f]; + } + + return salt; +} + +std::string PasswordHash::getPasswordHash() const { + return this->hashedPassword; +} + +std::string PasswordHash::getPasswordSalt() const { + return this->salt; +} + +std::string PasswordHash::hashPasswordWithSalt(const std::string & password) const { + const auto passwordWithSalt = password + salt; + return digestpp::sha512().absorb(passwordWithSalt).hexdigest(); +} diff --git a/src/Utils/PasswordHash.h b/src/Utils/PasswordHash.h new file mode 100644 index 0000000..b770897 --- /dev/null +++ b/src/Utils/PasswordHash.h @@ -0,0 +1,28 @@ +#ifndef PASSWORDHASH_H +#define PASSWORDHASH_H +#include + +class PasswordHash { + std::string hashedPassword; + std::string salt; +public: + explicit PasswordHash(const std::string&); + + bool operator==(const PasswordHash &) const; + + PasswordHash(const std::string&, std::string,bool generateHash = true); + + [[nodiscard]] std::string getPasswordHash() const; + + [[nodiscard]] std::string getPasswordSalt() const; + + [[nodiscard]] std::string hashPasswordWithSalt(const std::string&) const; + + static std::string generateSalt(); + + friend std::ostream& operator<<(std::ostream&, const PasswordHash&); +}; + + + +#endif //PASSWORDHASH_H diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..06a9835 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,66 @@ +#include +#include "Database/Database.h" + +#include "Database/Auth.h" +#include "EnvironmentReader/EnvironmentReader.h" +#include "Logger/Logger.h" +#include "Utils/EnvVarManager.h" + +void initializeDatabase() { + auto &logger = Logger::getInstance(); + EnvironmentReader::getEnvReader(); + try { + const std::string connString = EnvironmentReader::getConnString(); + Database::setConnString(connString); + Database::getDatabaseInstance(); + logger.log(LogLevel::INFO, "Connected to database"); + } catch (std::exception &e) { + logger.log(LogLevel::LOG_ERROR, "Error initializing database connection: " + std::string(e.what()) + '\n'); + throw std::runtime_error("Error initializing database connection" + std::string(e.what()) + '\n'); + } +} + +std::string promptCommand() { + std::string command; + while (true) { + std::cout << "Please choose 'Login' or 'Create account': "; + std::getline(std::cin, command); + if (command == "Login" || command == "Create account") { + std::flush(std::cout); + break; + } + std::cout << "Invalid option. "; + std::flush(std::cout); + } + return command; +} + +std::tuple promptUserDetails() { + std::string username, password; + std::cout << "Enter username: "; + std::cin >> username; + std::cout << "Enter password: "; + std::cin >> password; + return {username, password}; +} + +int main() { + Logger::create("Logs"); + auto &logger = Logger::getInstance(); + logger.log(LogLevel::INFO, "Application started"); + try { + initializeDatabase(); + } + catch (...) { + logger.log(LogLevel::LOG_ERROR, "Critical error encountered, application exiting"); + return 1; + } + const std::string command = promptCommand(); + auto [username, password] = promptUserDetails(); + const Auth auth(username, password); + std::optional currentUser; + if(command == "Login") currentUser = auth.login(); + else currentUser = auth.createAccount(); + std::cout<<*currentUser; + return 0; +} diff --git a/tastatura.txt b/tastatura.txt index a6d3c54..82c1663 100644 --- a/tastatura.txt +++ b/tastatura.txt @@ -1,2 +1,3 @@ -5 -11 22 33 44 55 +Create account +test +test \ No newline at end of file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..7987582 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,28 @@ +cmake_minimum_required(VERSION 3.26) + +project(Password-Keeper-Test-Runner) +set(TEST_PROJECT ${PROJECT_NAME} PARENT_SCOPE) + +FetchContent_Declare( + gtest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG main +) +FetchContent_MakeAvailable(gtest) + +add_executable(${PROJECT_NAME} + main.cpp + HashingTest.cpp + UserTest.cpp +) +include(${CMAKE_HELPER_DIR}/CompilerFlags.cmake) + +target_link_libraries(${PROJECT_NAME} PRIVATE ${SRC_PROJECT}_lib gtest gtest_main) + +install(TARGETS ${PROJECT_NAME} DESTINATION ${DESTINATION_DIR}) + +if (EXISTS ${PROJECT_ROOT}/.env) + copy_files(FILES .env) +endif () + +add_test(NAME ${PROJECT_NAME}_tests COMMAND ${PROJECT_NAME}) \ No newline at end of file diff --git a/tests/HashingTest.cpp b/tests/HashingTest.cpp new file mode 100644 index 0000000..a38aa34 --- /dev/null +++ b/tests/HashingTest.cpp @@ -0,0 +1,31 @@ +#include +#include + +#include "../src/User/User.h" +#include "../src/Utils/PasswordHash.h" + +TEST(HashingTest, HashFunctionReturnsExpectedValue) { + const auto password = "password"; + const auto actualHashedPassword = digestpp::sha512().absorb(password).hexdigest(); + const auto expectedHashedPassword = "b109f3bbbc244eb82441917ed06d618b9008dd09b3befd1b5e07394c706a8bb980b1d7785e5976ec049b46df5f1326af5a2ea6d103fd07c95385ffab0cacbc86"; + ASSERT_EQ(expectedHashedPassword, actualHashedPassword); +} + +TEST(HashingTest, SaltGeneratorIsUnique) { + const auto firstSalt = PasswordHash::generateSalt(); + const auto secondSalt = PasswordHash::generateSalt(); + ASSERT_NE(firstSalt, secondSalt); +} + +TEST(HashingTest, TwoUsersWithSamePasswordHaveDifferentHashes) { + const auto firstUser = User("first", "password"); + const auto secondUser = User("second", "password"); + ASSERT_NE(firstUser.getPasswordHash(), secondUser.getPasswordHash()); +} + +TEST(HashingTest, PasswordCanBeRehashedUsingSalt) { + const auto salt = PasswordHash::generateSalt(); + const PasswordHash passwordHash("password", salt); + const PasswordHash passwordHash2("password", salt); + ASSERT_EQ(passwordHash.getPasswordHash(), passwordHash2.getPasswordHash()); +} \ No newline at end of file diff --git a/tests/UserTest.cpp b/tests/UserTest.cpp new file mode 100644 index 0000000..db75071 --- /dev/null +++ b/tests/UserTest.cpp @@ -0,0 +1,61 @@ +#include + +#include "../src/Database/Database.h" +#include "../src/EnvironmentReader/EnvironmentReader.h" +#include "../src/Database/Auth.h" +#include "../src/Logger/Logger.h" + +class UserTest : public ::testing::Test { +protected: + static void SetUpTestSuite() { + Logger::create("Logs"); + EnvironmentReader::getEnvReader(); + const std::string connString = EnvironmentReader::getConnString(); + Database::setConnString(connString); + } +}; + +TEST_F(UserTest, AccountCreationIncreasesNumberOfAccounts) { + const auto &database = Database::getDatabaseInstance(); + const int numberOfUsersBefore = database.getNumberOfUsers(); + const Auth auth("AccountCreationIncreasesNumberOfAccounts","test"); + auto user = auth.createAccount(); + const int numberOfUsersAfter = database.getNumberOfUsers(); + ASSERT_EQ(numberOfUsersBefore+1, numberOfUsersAfter); +} + +TEST_F(UserTest, NewAccountDetailsTest) { + const auto &database = Database::getDatabaseInstance(); + std::string username = "NewAccountDetailsTest"; + const Auth auth(username,"test"); + const auto expectedUser = auth.createAccount(); + const auto actualUser = database.getUserByUsername(username); + ASSERT_EQ(expectedUser, actualUser); +} + +TEST_F(UserTest, NoDuplicateUsername) { + const std::string username = "NoDuplicateUsername"; + const Auth auth(username,"test"); + const auto expectedUser = auth.createAccount(); + const Auth auth1(username,"test2"); + // ReSharper disable once CppNoDiscardExpression + ASSERT_THROW(auth1.createAccount(),pqxx::unique_violation); +} + +TEST_F(UserTest, TestLoginValidCredentialsShouldSucceed) { + const std::string username = "TestLoginValid"; + const Auth auth(username,"test"); + const auto expectedUser = auth.createAccount(); + const Auth auth1(username,"test"); + const auto actualUser = auth1.login(); + ASSERT_EQ(expectedUser, actualUser); +} + +TEST_F(UserTest, TestLoginInvalidCredentialsShouldFail) { + const std::string username = "LoginTestInvalid"; + const Auth auth(username,"test"); + const auto expectedUser = auth.createAccount(); + const Auth auth1(username,"test1"); + // ReSharper disable once CppNoDiscardExpression + ASSERT_THROW(auth1.login(), std::exception); +} \ No newline at end of file diff --git a/tests/main.cpp b/tests/main.cpp new file mode 100644 index 0000000..d313203 --- /dev/null +++ b/tests/main.cpp @@ -0,0 +1,9 @@ +#include + +/// TODO Maybe add a script that initializes a brand new docker container and runs the tests in that container + +// This is where the test suite runs +int main(int argc, char **argv) { + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +}