From 48311f0cd96d607216679ab89ad553cbb31935b0 Mon Sep 17 00:00:00 2001 From: Charles Cabergs Date: Tue, 9 Dec 2025 18:32:39 +0100 Subject: [PATCH 1/2] Add curve functions wrappers --- tests/CMakeLists.txt | 1 + tests/curve.cpp | 36 ++++++++++++++++++++++++++++++ zmq.hpp | 52 ++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 tests/curve.cpp diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 3821c5c..3adfcc4 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -31,6 +31,7 @@ add_executable( monitor.cpp utilities.cpp timers.cpp + curve.cpp ) target_include_directories(unit_tests PUBLIC ${CATCH_MODULE_PATH}) diff --git a/tests/curve.cpp b/tests/curve.cpp new file mode 100644 index 0000000..9ad8a02 --- /dev/null +++ b/tests/curve.cpp @@ -0,0 +1,36 @@ +#include +#include + +#ifdef ZMQ_HAVE_CURVE + +TEST_CASE("curve_keypair", "[curve]") +{ + auto keys = zmq::curve_keypair(); + auto public_key = keys.first; + auto secret_key = keys.second; + CHECK(!public_key.empty()); + CHECK(!secret_key.empty()); +} + +TEST_CASE("curve_public", "[curve]") +{ + auto secret_key = "D:)Q[IlAW!ahhC2ac:9*A}h:p?([4%wOTJ%JR%cs"; + auto public_key = zmq::curve_public(secret_key); + CHECK(public_key == "Yne@$w-vo data{1,2,3,4,5,6,7,8}; + auto encoded = zmq::z85_encode(data); + CHECK(encoded.size() == std::string("0rJua1Qkhq").size()); + CHECK(encoded == "0rJua1Qkhq"); +} + +TEST_CASE("z85_decode", "[curve]") +{ + auto decoded = zmq::z85_decode("0rJua1Qkhq"); + CHECK(decoded == std::vector{1,2,3,4,5,6,7,8}); +} diff --git a/zmq.hpp b/zmq.hpp index ad0509e..2f4d0e0 100644 --- a/zmq.hpp +++ b/zmq.hpp @@ -107,6 +107,7 @@ #include #include +#include #include #include @@ -539,7 +540,7 @@ class message_t throw error_t(); memcpy(data(), data_, size_); } - + void rebuild(const std::string &str) { rebuild(str.data(), str.size()); @@ -2492,7 +2493,7 @@ class monitor_t (void) addr_; } - protected: + protected: bool process_event(short events) { zmq::message_t eventMsg; @@ -2874,6 +2875,53 @@ class timers #endif // defined(ZMQ_CPP11) && defined(ZMQ_HAVE_TIMERS) +#ifdef ZMQ_HAVE_CURVE + +inline std::pair curve_keypair() +{ + char public_key_buffer[41]; + char secret_key_buffer[41]; + int rc = zmq_curve_keypair(public_key_buffer, secret_key_buffer); + if (rc == -1) + throw zmq::error_t(); + return {public_key_buffer, secret_key_buffer}; +} + +inline std::string curve_public(const std::string& secret) +{ + if (secret.size() != 40) + throw std::runtime_error("Invalid secret string size"); + char public_key_buffer[41]; + int rc = zmq_curve_public(public_key_buffer, secret.c_str()); + if (rc == -1) + throw zmq::error_t(); + return public_key_buffer; +} + +#endif + +inline std::string z85_encode(const std::vector& data) +{ + size_t buffer_size = data.size() * size_t{6} / size_t{5} + 1; + std::string buffer(buffer_size, '\0'); + auto *result = zmq_z85_encode(&buffer[0], data.data(), data.size()); + if (result == nullptr) + throw zmq::error_t(); + while (buffer.back() == '\0') + buffer.pop_back(); + return buffer; +} + +inline std::vector z85_decode(const std::string& encoded) +{ + size_t dest_size = encoded.size() * size_t{4} / size_t{5}; + std::vector dest(dest_size); + auto *result = zmq_z85_decode(dest.data(), encoded.c_str()); + if (result == nullptr) + throw zmq::error_t(); + return dest; +} + } // namespace zmq #endif // __ZMQ_HPP_INCLUDED__ From 5b1cf576cb3a97d6fa3e745e2d9d5dc771fe1a47 Mon Sep 17 00:00:00 2001 From: Charles Cabergs Date: Wed, 17 Dec 2025 14:12:43 +0100 Subject: [PATCH 2/2] Add curve CI job and fix the libzmq build --- .github/workflows/ci.yml | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b310b27..da1ae17 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,14 +16,15 @@ jobs: cc: ["gcc-10"] cxx: ["g++-10"] drafts: ["ON"] + curve: ["OFF"] libzmq: ["4.3.5"] libzmqbuild: ["cmake"] include: # older libzmq and without draft - os: "ubuntu-22.04" cppstd: "11" - cc: "gcc-9" - cxx: "g++-9" + cc: "gcc-11" + cxx: "g++-11" drafts: "OFF" libzmq: "4.2.0" libzmqbuild: "pkgconfig" @@ -35,12 +36,21 @@ jobs: drafts: "OFF" libzmq: "4.3.5" libzmqbuild: "cmake" + # with curve + - os: "ubuntu-24.04" + cppstd: "23" + cc: "gcc-13" + cxx: "g++-13" + curve: "ON" + libzmq: "4.3.5" + libzmqbuild: "cmake" # coverage (gcc version should match gcov version) - os: "ubuntu-22.04" cppstd: "17" - cc: "gcc-9" - cxx: "g++-9" + cc: "gcc-11" + cxx: "g++-11" drafts: "ON" + curve: "ON" libzmq: "4.3.5" libzmqbuild: "cmake" coverage: "-DCOVERAGE=ON" @@ -108,11 +118,17 @@ jobs: - name: build_libzmq_cmake if: ${{ matrix.libzmqbuild == 'cmake' }} run: | + if [ ! "${{ matrix.os }}" = 'windows-2022' ]; then + export CXXFLAGS="-Wno-error=stringop-truncation -Wno-stringop-overflow" + export CFLAGS="-Wno-error=stringop-truncation -Wno-stringop-overflow" + fi cmake -Hlibzmq-${{ matrix.libzmq }} -Blibzmq-build ${{ matrix.platform}} \ -DWITH_PERF_TOOL=OFF \ -DZMQ_BUILD_TESTS=OFF \ + -DLIBZMQ_WERROR=OFF \ -DCMAKE_BUILD_TYPE=Release \ - -DENABLE_DRAFTS=${{ matrix.drafts }} + -DENABLE_DRAFTS=${{ matrix.drafts }} \ + -DENABLE_CURVE=${{ matrix.curve }} cmake --build libzmq-build --config ${BUILDTYPE} -j ${THREADS} echo "LIBZMQ=${PWD}/libzmq-build" >> ${GITHUB_ENV} @@ -126,6 +142,8 @@ jobs: if: ${{ matrix.libzmqbuild == 'pkgconfig' }} working-directory: libzmq-${{ matrix.libzmq }} run: | + export CXXFLAGS="-Wno-error=stringop-truncation -Wno-stringop-overflow" + export CFLAGS="-Wno-error=stringop-truncation -Wno-stringop-overflow" ./autogen.sh && ./configure --prefix=${PWD}/libzmq-build && make -j ${THREADS}