From 11d207d58f006ef6d2d074c919dd5084d2778a76 Mon Sep 17 00:00:00 2001 From: ImagineHaxing Date: Tue, 4 Aug 2026 21:27:06 +0300 Subject: [PATCH] Add Protocol::SignedMessage struct (not done) --- CMakeLists.txt | 9 ++++- Protocol/src/CMakeLists.txt | 5 +++ Protocol/src/include/protocol/protocol.hxx | 23 +++++++++++++ Protocol/src/protocol.cxx | 38 ++++++++++++++++++++++ Protocol/tests/CMakeLists.txt | 1 + Protocol/tests/test_protocol.cxx | 30 +++++++++++++++-- 6 files changed, 103 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4179071..0574895 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,12 +4,12 @@ project(Sabalty) set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +include(FetchContent) option(BUILD_TESTING "Build tests" OFF) if(BUILD_TESTING) enable_testing() - include(FetchContent) FetchContent_Declare( Catch2 GIT_REPOSITORY https://github.com/catchorg/Catch2.git @@ -21,5 +21,12 @@ if(BUILD_TESTING) include(Catch) endif() +FetchContent_Declare(Sodium + GIT_REPOSITORY https://github.com/robinlinden/libsodium-cmake.git + GIT_TAG cfebfd3da486d5a86c644c8b47067e5411c7599c # HEAD, last updated at 2026-02-28 +) +set(SODIUM_DISABLE_TESTS ON) +FetchContent_MakeAvailable(Sodium) + add_subdirectory(Server) add_subdirectory(Protocol) diff --git a/Protocol/src/CMakeLists.txt b/Protocol/src/CMakeLists.txt index a7907c3..8a2fb05 100644 --- a/Protocol/src/CMakeLists.txt +++ b/Protocol/src/CMakeLists.txt @@ -8,3 +8,8 @@ target_sources(Protocol BASE_DIRS include FILES include/protocol/protocol.hxx ) + +target_link_libraries(Protocol + PRIVATE + sodium +) diff --git a/Protocol/src/include/protocol/protocol.hxx b/Protocol/src/include/protocol/protocol.hxx index e69de29..652c189 100644 --- a/Protocol/src/include/protocol/protocol.hxx +++ b/Protocol/src/include/protocol/protocol.hxx @@ -0,0 +1,23 @@ +#pragma once + +#include "sodium/crypto_hash_sha256.h" +#include "sodium/crypto_sign.h" +#include +#include +namespace Protocol { + +struct SignedMessage { + unsigned char sender_key_fingerprint[crypto_hash_sha256_BYTES]; + std::string plaintext; + int64_t timestamp; + unsigned char sender_key_signature[crypto_sign_BYTES]; // signs fields 1-3 + + // Fills the fields and signs the plaintext + SignedMessage(unsigned char sender_pub_key[crypto_sign_PUBLICKEYBYTES], + unsigned char sender_priv_key[crypto_sign_SECRETKEYBYTES], + std::string plaintext); + + // TODO: bool isMessageTrusted(std::string pub_key); +}; + +} // namespace Protocol diff --git a/Protocol/src/protocol.cxx b/Protocol/src/protocol.cxx index e69de29..2af1f0a 100644 --- a/Protocol/src/protocol.cxx +++ b/Protocol/src/protocol.cxx @@ -0,0 +1,38 @@ +#include "sodium/crypto_sign_ed25519.h" +#include +#include +#include + +namespace Protocol { + +SignedMessage::SignedMessage( + unsigned char sender_pub_key[crypto_sign_PUBLICKEYBYTES], + unsigned char sender_priv_key[crypto_sign_SECRETKEYBYTES], + std::string plaintext) + : plaintext(plaintext) { + if (sodium_init() < 0) { + throw std::runtime_error("Failed to init sodium!"); + } + + timestamp = std::chrono::system_clock::now().time_since_epoch().count(); + crypto_hash_sha256(sender_key_fingerprint, sender_pub_key, + crypto_sign_PUBLICKEYBYTES); + + std::vector toBeSigned; + toBeSigned.reserve(sizeof(sender_key_fingerprint) + plaintext.size() + + sizeof(timestamp)); + + toBeSigned.insert(toBeSigned.cend(), sender_key_fingerprint, + sender_key_fingerprint + + sizeof(sender_key_fingerprint)); + toBeSigned.insert(toBeSigned.cend(), plaintext.data(), + plaintext.data() + plaintext.length()); + auto timestamp_bytes = reinterpret_cast(×tamp); + toBeSigned.insert(toBeSigned.cend(), timestamp_bytes, + timestamp_bytes + sizeof(timestamp)); + + crypto_sign_detached(sender_key_signature, nullptr, toBeSigned.data(), + toBeSigned.size(), sender_priv_key); +} + +} // namespace Protocol diff --git a/Protocol/tests/CMakeLists.txt b/Protocol/tests/CMakeLists.txt index 9a00cd7..40d0bc1 100644 --- a/Protocol/tests/CMakeLists.txt +++ b/Protocol/tests/CMakeLists.txt @@ -6,6 +6,7 @@ target_link_libraries(Protocol_tests PRIVATE Protocol Catch2::Catch2WithMain + sodium ) catch_discover_tests(Protocol_tests) diff --git a/Protocol/tests/test_protocol.cxx b/Protocol/tests/test_protocol.cxx index 58a94be..260a163 100644 --- a/Protocol/tests/test_protocol.cxx +++ b/Protocol/tests/test_protocol.cxx @@ -1,6 +1,32 @@ +#include "sodium/crypto_sign.h" #include #include +#include -TEST_CASE("something", "[stun]") { - SECTION("true") { REQUIRE(true); } +TEST_CASE("SignedMessage", "[protocol]") { + SECTION("sodium init") REQUIRE(sodium_init() >= 0); + + unsigned char pub_key[crypto_sign_PUBLICKEYBYTES]; + unsigned char priv_key[crypto_sign_SECRETKEYBYTES]; + crypto_sign_keypair(pub_key, priv_key); + + auto msg = Protocol::SignedMessage(pub_key, priv_key, "Hello, world!"); + std::vector toBeSigned; + toBeSigned.reserve(sizeof(msg.sender_key_fingerprint) + + msg.plaintext.size() + sizeof(msg.timestamp)); + + toBeSigned.insert(toBeSigned.cend(), msg.sender_key_fingerprint, + msg.sender_key_fingerprint + + sizeof(msg.sender_key_fingerprint)); + toBeSigned.insert(toBeSigned.cend(), msg.plaintext.data(), + msg.plaintext.data() + msg.plaintext.length()); + auto timestamp_bytes = reinterpret_cast(&msg.timestamp); + toBeSigned.insert(toBeSigned.cend(), timestamp_bytes, + timestamp_bytes + sizeof(msg.timestamp)); + + SECTION("signed message") { + REQUIRE(crypto_sign_verify_detached( + msg.sender_key_signature, toBeSigned.data(), + toBeSigned.size(), pub_key) == 0); + } }