diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b310b27..33df3a5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,8 +22,8 @@ jobs: # 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" @@ -38,8 +38,8 @@ jobs: # 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" libzmq: "4.3.5" libzmqbuild: "cmake" 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..8c93d80 --- /dev/null +++ b/tests/curve.cpp @@ -0,0 +1,30 @@ +#include +#include + +TEST_CASE("curve_keypair", "[curve]") +{ + auto [public_key, secret_key] = zmq::curve_keypair(); + 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..0a21358 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,49 @@ class timers #endif // defined(ZMQ_CPP11) && defined(ZMQ_HAVE_TIMERS) +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 std::pair{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; +} + +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.data(), 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__