Add curve functions wrappers (#671)

* Add curve functions wrappers

* Add curve CI job and fix the libzmq build
This commit is contained in:
Charles Cabergs
2025-12-19 09:27:11 +00:00
committed by GitHub
parent 8bace31b3d
commit fbbff88c07
4 changed files with 110 additions and 7 deletions

View File

@@ -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}

View File

@@ -31,6 +31,7 @@ add_executable(
monitor.cpp
utilities.cpp
timers.cpp
curve.cpp
)
target_include_directories(unit_tests PUBLIC ${CATCH_MODULE_PATH})

36
tests/curve.cpp Normal file
View File

@@ -0,0 +1,36 @@
#include <catch2/catch_all.hpp>
#include <zmq.hpp>
#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<fVvi]a<NY6T1ed:M$fCG*[IaLV{hID");
}
#endif
TEST_CASE("z85_encode", "[curve]")
{
std::vector<uint8_t> 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<uint8_t>{1,2,3,4,5,6,7,8});
}

52
zmq.hpp
View File

@@ -107,6 +107,7 @@
#include <cassert>
#include <cstring>
#include <cstdint>
#include <type_traits>
#include <algorithm>
@@ -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<std::string, std::string> 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<uint8_t>& 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<uint8_t> z85_decode(const std::string& encoded)
{
size_t dest_size = encoded.size() * size_t{4} / size_t{5};
std::vector<uint8_t> 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__