security/test_message_signing.cpp¶
Unit tests for MessageSigning — verify, tamper rejection, replay protection. More...
Functions¶
| Name | |
|---|---|
| TEST(MessageSigning , VerifyValidSignature ) | |
| TEST(MessageSigning , VerifyTamperedPayload ) | |
| TEST(MessageSigning , VerifyWrongKey ) | |
| TEST(MessageSigning , VerifyEmptySignature ) | |
| TEST(MessageSigning , VerifyTruncatedSignature ) | |
| TEST(MessageSigning , VerifyAndStripValid ) | |
| TEST(MessageSigning , VerifyAndStripExpiredTimestamp ) | |
| TEST(MessageSigning , GenerateNonce_Returns32ByteHexString ) | |
| TEST(MessageSigning , GenerateNonce_IsUnique ) | |
| TEST(MessageSigning , AttachSignature_ValidPayload_AppendsSigField ) | |
| TEST(MessageSigning , VerifyAndStrip_MalformedJson_ReturnsFalse ) | |
| TEST(MessageSigning , VerifyAndStrip_EmptyPayload_ReturnsFalse ) |
Detailed Description¶
Unit tests for MessageSigning — verify, tamper rejection, replay protection.
Date: 2026-05-28 GSD Executor
Functions Documentation¶
function TEST¶
function TEST¶
function TEST¶
function TEST¶
function TEST¶
function TEST¶
function TEST¶
function TEST¶
function TEST¶
function TEST¶
function TEST¶
function TEST¶
Source code¶
#include "security/message_signing.hpp"
#include "security/node_identity.hpp"
#include <gtest/gtest.h>
#include <iomanip>
#include <sstream>
#include <string>
#include <vector>
using namespace sgns::neoswarm;
using namespace sgns::neoswarm::security;
namespace
{
std::string PubKeyToHex( const NodeIdentity::PubKey& key )
{
std::ostringstream oss;
for ( auto b : key )
{
oss << std::hex << std::setw( 2 ) << std::setfill( '0' ) << static_cast<int>( b );
}
return oss.str();
}
} // namespace
// =======================================================================
// Signature Verification
// =======================================================================
TEST( MessageSigning, VerifyValidSignature )
{
NodeIdentity ident;
ASSERT_TRUE( ident.Generate().has_value() );
const std::string pubKeyHex = PubKeyToHex( ident.GetPublicKey() );
MessageSigning signer( ident );
const std::string payload = R"({"msg":"hello"})";
auto sig = signer.Sign( payload );
ASSERT_TRUE( sig.has_value() );
ASSERT_FALSE( sig.value().empty() );
EXPECT_TRUE( MessageSigning::Verify( payload, sig.value(), pubKeyHex ) );
}
TEST( MessageSigning, VerifyTamperedPayload )
{
NodeIdentity ident;
ASSERT_TRUE( ident.Generate().has_value() );
const std::string pubKeyHex = PubKeyToHex( ident.GetPublicKey() );
MessageSigning signer( ident );
const std::string payload = R"({"msg":"hello"})";
auto sig = signer.Sign( payload );
ASSERT_TRUE( sig.has_value() );
const std::string tampered = R"({"msg":"world"})";
EXPECT_FALSE( MessageSigning::Verify( tampered, sig.value(), pubKeyHex ) );
}
TEST( MessageSigning, VerifyWrongKey )
{
NodeIdentity identA;
NodeIdentity identB;
ASSERT_TRUE( identA.Generate().has_value() );
ASSERT_TRUE( identB.Generate().has_value() );
const std::string pubKeyB = PubKeyToHex( identB.GetPublicKey() );
MessageSigning signerA( identA );
const std::string payload = R"({"msg":"hello"})";
auto sig = signerA.Sign( payload );
ASSERT_TRUE( sig.has_value() );
EXPECT_FALSE( MessageSigning::Verify( payload, sig.value(), pubKeyB ) );
}
TEST( MessageSigning, VerifyEmptySignature )
{
NodeIdentity ident;
ASSERT_TRUE( ident.Generate().has_value() );
const std::string pubKeyHex = PubKeyToHex( ident.GetPublicKey() );
EXPECT_FALSE( MessageSigning::Verify( "payload", {}, pubKeyHex ) );
}
TEST( MessageSigning, VerifyTruncatedSignature )
{
NodeIdentity ident;
ASSERT_TRUE( ident.Generate().has_value() );
const std::string pubKeyHex = PubKeyToHex( ident.GetPublicKey() );
std::vector<uint8_t> truncated = { 0x30, 0x06, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01 };
EXPECT_FALSE( MessageSigning::Verify( "payload", truncated, pubKeyHex ) );
}
// =======================================================================
// Nonce + Timestamp Replay Protection
// =======================================================================
TEST( MessageSigning, VerifyAndStripValid )
{
NodeIdentity ident;
ASSERT_TRUE( ident.Generate().has_value() );
const std::string pubKeyHex = PubKeyToHex( ident.GetPublicKey() );
MessageSigning signer( ident );
const std::string original = R"({"msg":"hello"})";
std::string payload = signer.AttachSignature( original );
EXPECT_NE( payload, original );
EXPECT_TRUE( MessageSigning::VerifyAndStrip( payload, pubKeyHex ) );
EXPECT_EQ( payload, original );
}
TEST( MessageSigning, VerifyAndStripExpiredTimestamp )
{
NodeIdentity ident;
ASSERT_TRUE( ident.Generate().has_value() );
const std::string pubKeyHex = PubKeyToHex( ident.GetPublicKey() );
MessageSigning signer( ident );
std::string payload = signer.AttachSignature( R"({"msg":"test"})" );
auto tsPos = payload.rfind( ",\"ts\":" );
ASSERT_NE( tsPos, std::string::npos );
uint64_t oldTs = MessageSigning::CurrentTimestampMs() - 61000;
auto tsVal = payload.find_first_of( "0123456789", tsPos + 6 );
auto tsEnd = payload.find_first_of( ",}", tsVal );
ASSERT_NE( tsVal, std::string::npos );
ASSERT_NE( tsEnd, std::string::npos );
payload.replace( tsVal, tsEnd - tsVal, std::to_string( oldTs ) );
EXPECT_FALSE( MessageSigning::VerifyAndStrip( payload, pubKeyHex ) );
}
TEST( MessageSigning, GenerateNonce_Returns32ByteHexString )
{
std::string nonce = MessageSigning::GenerateNonce();
EXPECT_EQ( nonce.size(), 64 );
for ( char c : nonce )
{
EXPECT_TRUE( ( c >= '0' && c <= '9' ) || ( c >= 'a' && c <= 'f' ) );
}
}
TEST( MessageSigning, GenerateNonce_IsUnique )
{
std::string n1 = MessageSigning::GenerateNonce();
std::string n2 = MessageSigning::GenerateNonce();
EXPECT_NE( n1, n2 );
}
TEST( MessageSigning, AttachSignature_ValidPayload_AppendsSigField )
{
NodeIdentity ident;
ASSERT_TRUE( ident.Generate().has_value() );
MessageSigning signer( ident );
std::string payload = R"({"op":"test","data":"hello"})";
std::string signedPayload = signer.AttachSignature( payload );
EXPECT_NE( signedPayload.find( "\"sig\"" ), std::string::npos );
EXPECT_NE( signedPayload.find( "\"nonce\"" ), std::string::npos );
}
TEST( MessageSigning, VerifyAndStrip_MalformedJson_ReturnsFalse )
{
NodeIdentity ident;
ASSERT_TRUE( ident.Generate().has_value() );
std::string pubKeyHex = PubKeyToHex( ident.GetPublicKey() );
std::string payload = "not json";
EXPECT_FALSE( MessageSigning::VerifyAndStrip( payload, pubKeyHex ) );
}
TEST( MessageSigning, VerifyAndStrip_EmptyPayload_ReturnsFalse )
{
NodeIdentity ident;
ASSERT_TRUE( ident.Generate().has_value() );
std::string pubKeyHex = PubKeyToHex( ident.GetPublicKey() );
std::string payload;
EXPECT_FALSE( MessageSigning::VerifyAndStrip( payload, pubKeyHex ) );
}
Updated on 2026-07-25 at 22:56:57 +0000