diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4c2c07f..90c4dfa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,11 +7,98 @@ on: branches: [ main, dev ] jobs: - check-repo: + build-test-smoke: runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + - name: debug-fast + hypericum_paramset: debug + kryzhovnik_paramset: debug + - name: baseline-medium + hypericum_paramset: m_128_20 + kryzhovnik_paramset: medium + timeout-minutes: 25 steps: - name: Checkout repository with submodules uses: actions/checkout@v4 with: submodules: recursive + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y \ + build-essential \ + cmake \ + pkg-config \ + libssl-dev \ + libcppunit-dev + + - name: Configure (${{ matrix.name }}) + run: | + cmake -S . -B build-${{ matrix.name }} \ + -DHYPERICUM_PARAMSET=${{ matrix.hypericum_paramset }} \ + -DKRYZHOVNIK_PARAMSET=${{ matrix.kryzhovnik_paramset }} + + - name: Build (${{ matrix.name }}) + run: | + cmake --build build-${{ matrix.name }} --parallel + + - name: CTest core checks (${{ matrix.name }}) + run: | + ctest --test-dir build-${{ matrix.name }} \ + --output-on-failure \ + -R 'kryzhovnik|adapters_smoke|merkletree_test' + + - name: Benchmark smoke (${{ matrix.name }}) + run: | + ./build-${{ matrix.name }}/bench/bench_seq \ + --algo hypericum \ + --params ${{ matrix.hypericum_paramset }} \ + --batch-size 1 \ + --iters 1 \ + --verify 1 \ + --out-csv /tmp/h_${{ matrix.name }}.csv \ + --out-json /tmp/h_${{ matrix.name }}.json + + ./build-${{ matrix.name }}/bench/bench_seq \ + --algo shipovnik \ + --params default \ + --batch-size 1 \ + --iters 1 \ + --verify 1 \ + --out-csv /tmp/s_${{ matrix.name }}.csv \ + --out-json /tmp/s_${{ matrix.name }}.json + + ./build-${{ matrix.name }}/bench/bench_seq \ + --algo kryzhovnik \ + --params ${{ matrix.kryzhovnik_paramset }} \ + --batch-size 1 \ + --iters 1 \ + --verify 1 \ + --out-csv /tmp/k_${{ matrix.name }}.csv \ + --out-json /tmp/k_${{ matrix.name }}.json + + benchmark-script-smoke: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - name: Checkout repository with submodules + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Verify benchmark script CLI and dry-run + run: | + bash scripts/benchmark.sh --help + bash scripts/benchmark.sh \ + --dry-run \ + --algo hypericum \ + --batch-sizes 1 \ + --iters 1 \ + --verify 1 \ + --hypericum-params debug \ + --kryzhovnik-params debug + diff --git a/README.md b/README.md index 99630c9..1f7ff79 100644 --- a/README.md +++ b/README.md @@ -95,6 +95,10 @@ cmake -S . -B build \ cmake --build build --parallel ``` +Supported Hypericum values: `b_256_64`, `m_256_64`, `b_256_20`, `m_256_20`, `b_128_20`, `m_128_20`, `debug`. + +`debug` is an aggressive speed-oriented research profile for benchmarks and diagnostics. + Supported Kryzhovnik values: `small`, `medium`, `large`, `debug`. `debug` is intended for fast diagnostics and troubleshooting, not security evaluation. @@ -105,7 +109,7 @@ The benchmark helper script also supports separate flags: ./scripts/benchmark.sh \ --algo kryzhovnik \ --kryzhovnik-params small \ - --hypericum-params m_128_20 + --hypericum-params debug ``` Note: Kryzhovnik constants are aligned with `security.sage` for `small/medium/large`. Keep validating against the official specification before production use. diff --git a/README_ru.md b/README_ru.md index ecc2cb8..40e75ac 100644 --- a/README_ru.md +++ b/README_ru.md @@ -100,6 +100,10 @@ cmake -S . -B build \ cmake --build build --parallel ``` +Поддерживаемые значения для Hypericum: `b_256_64`, `m_256_64`, `b_256_20`, `m_256_20`, `b_128_20`, `m_128_20`, `debug`. + +`debug` — агрессивный исследовательский профиль, ориентированный на скорость для benchmark/diagnostics. + Поддерживаемые значения для Kryzhovnik: `small`, `medium`, `large`, `debug`. `debug` предназначен для быстрой диагностики и отладки, а не для оценки стойкости. @@ -110,7 +114,7 @@ cmake --build build --parallel ./scripts/benchmark.sh \ --algo kryzhovnik \ --kryzhovnik-params small \ - --hypericum-params m_128_20 + --hypericum-params debug ``` Примечание: константы Kryzhovnik для `small/medium/large` синхронизированы со скриптом `security.sage`; перед production-использованием их нужно дополнительно верифицировать по официальной спецификации. diff --git a/scripts/benchmark.sh b/scripts/benchmark.sh index 33e2355..9487162 100755 --- a/scripts/benchmark.sh +++ b/scripts/benchmark.sh @@ -5,8 +5,8 @@ ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" BUILD_DIR="${ROOT_DIR}/build" OUTPUT_DIR="${ROOT_DIR}/results/bench-$(date +%Y%m%d-%H%M%S)" ALGOS="all" -HYPERICUM_PARAMS="m_128_20" -KRYZHOVNIK_PARAMS="medium" +HYPERICUM_PARAMS="debug" +KRYZHOVNIK_PARAMS="debug" BATCH_SIZES="1,2,4,8,16,32,64" ITERS=100 MSG_SIZE=1024 @@ -19,10 +19,10 @@ usage() { cat < - --hypericum-params (default: m_128_20) - --kryzhovnik-params (default: medium) + --hypericum-params (default: debug) + --kryzhovnik-params (default: debug) --params (legacy: sets hypericum; - also sets kryzhovnik when value is small|medium|large) + also sets kryzhovnik when value is small|medium|large|debug) --batch-sizes (default: 1,2,4,8,16,32,64) --iters (default: 100) diff --git a/third_party/CMakeLists.txt b/third_party/CMakeLists.txt index 9a550ec..85714cf 100644 --- a/third_party/CMakeLists.txt +++ b/third_party/CMakeLists.txt @@ -44,16 +44,21 @@ set(HYPERICUM_DIR ${CMAKE_CURRENT_SOURCE_DIR}/hypericum) if(TARGET streebog AND EXISTS "${HYPERICUM_DIR}/hypericum.c") set(HYPERICUM_PARAMSET "b_256_64" CACHE STRING "Select a hypericum parameter set") set_property(CACHE HYPERICUM_PARAMSET PROPERTY STRINGS - "b_256_64" "m_256_64" "b_256_20" "m_256_20" "b_128_20" "m_128_20") + "b_256_64" "m_256_64" "b_256_20" "m_256_20" "b_128_20" "m_128_20" "debug") if(NOT HYPERICUM_PARAMSET) set(HYPERICUM_PARAMSET "b_256_64") endif() message(STATUS "Using Hypericum parameter set ${HYPERICUM_PARAMSET}") - # Generate current-paramset.h from .h.in using HYPERICUM_PARAMSET as PARAMSET - set(PARAMSET ${HYPERICUM_PARAMSET}) + if(HYPERICUM_PARAMSET STREQUAL "debug") + set(HYPERICUM_PARAMSET_INCLUDE "paramsets/hypericum/params_debug.h") + else() + set(HYPERICUM_PARAMSET_INCLUDE "paramsets/params_${HYPERICUM_PARAMSET}.h") + endif() + + # Generate current-paramset.h in build tree from superproject template. configure_file( - ${HYPERICUM_DIR}/current-paramset.h.in + ${CMAKE_CURRENT_SOURCE_DIR}/hypericum-current-paramset.h.in ${CMAKE_CURRENT_BINARY_DIR}/hypericum/current-paramset.h ) @@ -79,6 +84,7 @@ if(TARGET streebog AND EXISTS "${HYPERICUM_DIR}/hypericum.c") PUBLIC $ $ + $ PRIVATE ${HYPERICUM_DIR} ${STREEBOG_DIR} diff --git a/third_party/hypericum-current-paramset.h.in b/third_party/hypericum-current-paramset.h.in new file mode 100644 index 0000000..d52da51 --- /dev/null +++ b/third_party/hypericum-current-paramset.h.in @@ -0,0 +1,8 @@ +/* + Superproject-generated Hypericum paramset selector. + This file allows local paramset overrides without patching hypericum submodule. +*/ + +#pragma once + +#include "@HYPERICUM_PARAMSET_INCLUDE@" diff --git a/third_party/paramsets/hypericum/params_debug.h b/third_party/paramsets/hypericum/params_debug.h new file mode 100644 index 0000000..93c9a74 --- /dev/null +++ b/third_party/paramsets/hypericum/params_debug.h @@ -0,0 +1,59 @@ +/* + This product is distributed under 2-term BSD-license terms + + Copyright (c) 2023, QApp. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#pragma once + +#include + +/* Hypericum debug profile: fast diagnostics only. */ +/* Height of the hypertree. */ +#define HYP_H 10 +/* Hypertree layers count */ +#define HYP_D 2 +/* FORS+C tree height */ +#define HYP_B 5 +/* FORS+C trees count plus one */ +#define HYP_K 8 + +/* + * checks whether bits in interval [(k - 1) * b; k * b) of digest are all 0 + * this variant is generic and works for any HYP_B/HYP_K combination. + */ +static uint8_t md_suffix_nonzero(const uint8_t* digest) +{ + uint16_t i; + uint16_t start = (uint16_t)((HYP_K - 1) * HYP_B); + uint8_t acc = 0; + + for (i = 0; i < HYP_B; ++i) { + uint16_t bit_index = (uint16_t)(start + i); + uint16_t byte_index = (uint16_t)(bit_index >> 3); + uint8_t bit_in_byte = (uint8_t)(7U - (bit_index & 7U)); + acc |= (uint8_t)(digest[byte_index] & (uint8_t)(1U << bit_in_byte)); + } + + return acc; +}