Files
SimpleRemoter/test/unit/network/HeaderTest.cpp
2026-04-19 22:55:21 +02:00

643 lines
18 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* @file HeaderTest.cpp
* @brief 协议头验证和加密测试
*
* 测试覆盖:
* - 协议头格式和常量
* - 加密/解密函数正确性
* - 多版本头部识别
* - 头部生成和验证往返
*/
#include <gtest/gtest.h>
#include <cstring>
#include <cstdint>
#include <vector>
#include <array>
// ============================================
// 协议常量定义(测试专用副本)
// ============================================
#define MSG_HEADER "HELL"
const int FLAG_COMPLEN = 4;
const int FLAG_LENGTH = 8;
const int HDR_LENGTH = FLAG_LENGTH + 2 * sizeof(unsigned int); // 16
const int MIN_COMLEN = 12;
enum HeaderEncType {
HeaderEncUnknown = -1,
HeaderEncNone,
HeaderEncV0,
HeaderEncV1,
HeaderEncV2,
HeaderEncV3,
HeaderEncV4,
HeaderEncV5,
HeaderEncV6,
HeaderEncNum,
};
enum FlagType {
FLAG_WINOS = -1,
FLAG_UNKNOWN = 0,
FLAG_SHINE = 1,
FLAG_FUCK = 2,
FLAG_HELLO = 3,
FLAG_HELL = 4,
};
// ============================================
// 加密/解密函数(测试专用副本)
// ============================================
inline void default_encrypt(unsigned char* data, size_t length, unsigned char key)
{
data[FLAG_LENGTH - 2] = data[FLAG_LENGTH - 1] = 0;
}
inline void default_decrypt(unsigned char* data, size_t length, unsigned char key)
{
}
inline void encrypt(unsigned char* data, size_t length, unsigned char key)
{
if (key == 0) return;
for (size_t i = 0; i < length; ++i) {
unsigned char k = static_cast<unsigned char>(key ^ (i * 31));
int value = static_cast<int>(data[i]);
switch (i % 4) {
case 0:
value += k;
break;
case 1:
value = value ^ k;
break;
case 2:
value -= k;
break;
case 3:
value = ~(value ^ k);
break;
}
data[i] = static_cast<unsigned char>(value & 0xFF);
}
}
inline void decrypt(unsigned char* data, size_t length, unsigned char key)
{
if (key == 0) return;
for (size_t i = 0; i < length; ++i) {
unsigned char k = static_cast<unsigned char>(key ^ (i * 31));
int value = static_cast<int>(data[i]);
switch (i % 4) {
case 0:
value -= k;
break;
case 1:
value = value ^ k;
break;
case 2:
value += k;
break;
case 3:
value = ~(value) ^ k;
break;
}
data[i] = static_cast<unsigned char>(value & 0xFF);
}
}
// ============================================
// HeaderFlag 结构体
// ============================================
typedef struct HeaderFlag {
char Data[FLAG_LENGTH + 1];
HeaderFlag(const char header[FLAG_LENGTH + 1])
{
memcpy(Data, header, sizeof(Data));
}
char& operator[](int i)
{
return Data[i];
}
const char operator[](int i) const
{
return Data[i];
}
const char* data() const
{
return Data;
}
} HeaderFlag;
typedef void (*EncFun)(unsigned char* data, size_t length, unsigned char key);
typedef void (*DecFun)(unsigned char* data, size_t length, unsigned char key);
// ============================================
// 头部生成函数
// ============================================
inline HeaderFlag GetHead(EncFun enc, unsigned char fixedKey = 0)
{
char header[FLAG_LENGTH + 1] = { 'H','E','L','L', 0 };
HeaderFlag H(header);
unsigned char key = (fixedKey != 0) ? fixedKey : (time(0) % 256);
H[FLAG_LENGTH - 2] = key;
H[FLAG_LENGTH - 1] = ~key;
enc((unsigned char*)H.data(), FLAG_COMPLEN, H[FLAG_LENGTH - 2]);
return H;
}
// ============================================
// 头部验证函数
// ============================================
inline int compare(const char *flag, const char *magic, int len, DecFun dec, unsigned char key)
{
unsigned char buf[32] = {};
memcpy(buf, flag, MIN_COMLEN);
dec(buf, len, key);
if (memcmp(buf, magic, len) == 0) {
memcpy((void*)flag, buf, MIN_COMLEN);
return 0;
}
return -1;
}
inline FlagType CheckHead(const char* flag, DecFun dec)
{
FlagType type = FLAG_UNKNOWN;
if (compare(flag, MSG_HEADER, FLAG_COMPLEN, dec, flag[6]) == 0) {
type = FLAG_HELL;
} else if (compare(flag, "Shine", 5, dec, 0) == 0) {
type = FLAG_SHINE;
} else if (compare(flag, "<<FUCK>>", 8, dec, flag[9]) == 0) {
type = FLAG_FUCK;
} else if (compare(flag, "Hello?", 6, dec, flag[6]) == 0) {
type = FLAG_HELLO;
} else {
type = FLAG_UNKNOWN;
}
return type;
}
inline FlagType CheckHeadMulti(char* flag, HeaderEncType& funcHit)
{
static const DecFun methods[] = { default_decrypt, decrypt };
static const int methodNum = sizeof(methods) / sizeof(DecFun);
char buffer[MIN_COMLEN + 4] = {};
for (int i = 0; i < methodNum; ++i) {
memcpy(buffer, flag, MIN_COMLEN);
FlagType type = CheckHead(buffer, methods[i]);
if (type != FLAG_UNKNOWN) {
memcpy(flag, buffer, MIN_COMLEN);
funcHit = HeaderEncType(i);
return type;
}
}
funcHit = HeaderEncUnknown;
return FLAG_UNKNOWN;
}
// ============================================
// 协议常量测试
// ============================================
class HeaderConstantsTest : public ::testing::Test {};
TEST_F(HeaderConstantsTest, FlagLength) {
EXPECT_EQ(FLAG_LENGTH, 8);
}
TEST_F(HeaderConstantsTest, FlagCompLen) {
EXPECT_EQ(FLAG_COMPLEN, 4);
}
TEST_F(HeaderConstantsTest, HdrLength) {
// FLAG_LENGTH(8) + 2 * sizeof(uint32_t)(8) = 16
EXPECT_EQ(HDR_LENGTH, 16);
}
TEST_F(HeaderConstantsTest, MinComLen) {
EXPECT_EQ(MIN_COMLEN, 12);
}
TEST_F(HeaderConstantsTest, MsgHeader) {
EXPECT_STREQ(MSG_HEADER, "HELL");
EXPECT_EQ(strlen(MSG_HEADER), 4u);
}
// ============================================
// 加密/解密测试
// ============================================
class EncryptionTest : public ::testing::Test {};
TEST_F(EncryptionTest, ZeroKeyNoOp) {
unsigned char data[] = {0x01, 0x02, 0x03, 0x04, 0x05};
unsigned char original[] = {0x01, 0x02, 0x03, 0x04, 0x05};
encrypt(data, 5, 0);
EXPECT_EQ(memcmp(data, original, 5), 0);
decrypt(data, 5, 0);
EXPECT_EQ(memcmp(data, original, 5), 0);
}
TEST_F(EncryptionTest, EncryptDecryptRoundTrip) {
unsigned char original[] = {0x48, 0x45, 0x4C, 0x4C}; // "HELL"
unsigned char data[4];
memcpy(data, original, 4);
unsigned char key = 0x42;
encrypt(data, 4, key);
// 加密后应该不同
EXPECT_NE(memcmp(data, original, 4), 0);
decrypt(data, 4, key);
// 解密后应该恢复
EXPECT_EQ(memcmp(data, original, 4), 0);
}
TEST_F(EncryptionTest, DifferentKeysProduceDifferentResults) {
unsigned char data1[] = {0x48, 0x45, 0x4C, 0x4C};
unsigned char data2[] = {0x48, 0x45, 0x4C, 0x4C};
encrypt(data1, 4, 0x10);
encrypt(data2, 4, 0x20);
EXPECT_NE(memcmp(data1, data2, 4), 0);
}
TEST_F(EncryptionTest, PositionDependentEncryption) {
// 相同值在不同位置加密结果不同
unsigned char data[] = {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA};
unsigned char original[] = {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA};
encrypt(data, 8, 0x55);
// 验证加密后值不全相同(位置相关加密)
bool allSame = true;
for (int i = 1; i < 8; ++i) {
if (data[i] != data[0]) {
allSame = false;
break;
}
}
EXPECT_FALSE(allSame);
// 验证解密恢复
decrypt(data, 8, 0x55);
EXPECT_EQ(memcmp(data, original, 8), 0);
}
TEST_F(EncryptionTest, AllKeyValues) {
// 测试所有可能的密钥值
unsigned char original[] = {0x12, 0x34, 0x56, 0x78};
for (int key = 1; key < 256; ++key) {
unsigned char data[4];
memcpy(data, original, 4);
encrypt(data, 4, static_cast<unsigned char>(key));
decrypt(data, 4, static_cast<unsigned char>(key));
EXPECT_EQ(memcmp(data, original, 4), 0) << "Failed for key: " << key;
}
}
TEST_F(EncryptionTest, LargeDataRoundTrip) {
std::vector<unsigned char> original(1000);
for (size_t i = 0; i < original.size(); ++i) {
original[i] = static_cast<unsigned char>(i & 0xFF);
}
std::vector<unsigned char> data = original;
unsigned char key = 0x7F;
encrypt(data.data(), data.size(), key);
decrypt(data.data(), data.size(), key);
EXPECT_EQ(data, original);
}
// ============================================
// HeaderFlag 测试
// ============================================
class HeaderFlagTest : public ::testing::Test {};
TEST_F(HeaderFlagTest, Construction) {
char header[FLAG_LENGTH + 1] = { 'H','E','L','L', 0, 0, 0, 0, 0 };
HeaderFlag hf(header);
EXPECT_EQ(hf[0], 'H');
EXPECT_EQ(hf[1], 'E');
EXPECT_EQ(hf[2], 'L');
EXPECT_EQ(hf[3], 'L');
}
TEST_F(HeaderFlagTest, DataAccess) {
char header[FLAG_LENGTH + 1] = { 'T','E','S','T', 0x12, 0x34, 0x56, 0x78, 0 };
HeaderFlag hf(header);
EXPECT_EQ(memcmp(hf.data(), "TEST", 4), 0);
EXPECT_EQ(static_cast<unsigned char>(hf[4]), 0x12);
EXPECT_EQ(static_cast<unsigned char>(hf[5]), 0x34);
}
TEST_F(HeaderFlagTest, Modification) {
char header[FLAG_LENGTH + 1] = { 0 };
HeaderFlag hf(header);
hf[0] = 'A';
hf[1] = 'B';
EXPECT_EQ(hf[0], 'A');
EXPECT_EQ(hf[1], 'B');
}
// ============================================
// GetHead 测试
// ============================================
class GetHeadTest : public ::testing::Test {};
TEST_F(GetHeadTest, GeneratesValidHeader) {
HeaderFlag hf = GetHead(default_encrypt, 0x42);
// 检查基础格式
EXPECT_EQ(hf[0], 'H');
EXPECT_EQ(hf[1], 'E');
EXPECT_EQ(hf[2], 'L');
EXPECT_EQ(hf[3], 'L');
}
TEST_F(GetHeadTest, KeyAndInverseKey) {
unsigned char key = 0x42;
HeaderFlag hf = GetHead(default_encrypt, key);
// 使用 default_encrypt 时key 位置被清零
// 但我们需要验证生成逻辑
char rawHeader[FLAG_LENGTH + 1] = { 'H','E','L','L', 0 };
HeaderFlag expected(rawHeader);
expected[FLAG_LENGTH - 2] = key;
expected[FLAG_LENGTH - 1] = ~key;
default_encrypt((unsigned char*)expected.data(), FLAG_COMPLEN, expected[FLAG_LENGTH - 2]);
EXPECT_EQ(memcmp(hf.data(), expected.data(), FLAG_LENGTH), 0);
}
TEST_F(GetHeadTest, EncryptedHeader) {
unsigned char key = 0x55;
HeaderFlag hf = GetHead(encrypt, key);
// 头部应该被加密,不再是明文 "HELL"
EXPECT_NE(memcmp(hf.data(), "HELL", 4), 0);
// 密钥应该在正确位置
unsigned char storedKey = static_cast<unsigned char>(hf[FLAG_LENGTH - 2]);
unsigned char inverseKey = static_cast<unsigned char>(hf[FLAG_LENGTH - 1]);
EXPECT_EQ(storedKey, key);
EXPECT_EQ(inverseKey, static_cast<unsigned char>(~key));
}
// ============================================
// CheckHead 测试
// ============================================
class CheckHeadTest : public ::testing::Test {};
TEST_F(CheckHeadTest, IdentifyHellFlag) {
char header[MIN_COMLEN + 4] = { 'H','E','L','L', 0, 0, 0x42, static_cast<char>(~0x42), 0 };
FlagType type = CheckHead(header, default_decrypt);
EXPECT_EQ(type, FLAG_HELL);
}
TEST_F(CheckHeadTest, IdentifyShineFlag) {
char header[MIN_COMLEN + 4] = { 'S','h','i','n','e', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
FlagType type = CheckHead(header, default_decrypt);
EXPECT_EQ(type, FLAG_SHINE);
}
TEST_F(CheckHeadTest, UnknownFlag) {
char header[MIN_COMLEN + 4] = { 'X','Y','Z','W', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
FlagType type = CheckHead(header, default_decrypt);
EXPECT_EQ(type, FLAG_UNKNOWN);
}
TEST_F(CheckHeadTest, EncryptedHellFlag) {
// 生成加密的头部
unsigned char key = 0x33;
char header[FLAG_LENGTH + 1] = { 'H','E','L','L', 0, 0, 0, 0, 0 };
header[FLAG_LENGTH - 2] = key;
header[FLAG_LENGTH - 1] = ~key;
encrypt((unsigned char*)header, FLAG_COMPLEN, key);
char buffer[MIN_COMLEN + 4] = {};
memcpy(buffer, header, FLAG_LENGTH);
FlagType type = CheckHead(buffer, decrypt);
EXPECT_EQ(type, FLAG_HELL);
}
// ============================================
// CheckHeadMulti 测试
// ============================================
class CheckHeadMultiTest : public ::testing::Test {};
TEST_F(CheckHeadMultiTest, PlainTextHeader) {
char header[MIN_COMLEN + 4] = { 'H','E','L','L', 0, 0, 0x42, static_cast<char>(~0x42), 0 };
HeaderEncType encType;
FlagType type = CheckHeadMulti(header, encType);
EXPECT_EQ(type, FLAG_HELL);
EXPECT_EQ(encType, HeaderEncNone);
}
TEST_F(CheckHeadMultiTest, EncryptedHeader) {
unsigned char key = 0x77;
char header[MIN_COMLEN + 4] = { 'H','E','L','L', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
header[FLAG_LENGTH - 2] = key;
header[FLAG_LENGTH - 1] = ~key;
encrypt((unsigned char*)header, FLAG_COMPLEN, key);
HeaderEncType encType;
FlagType type = CheckHeadMulti(header, encType);
EXPECT_EQ(type, FLAG_HELL);
EXPECT_EQ(encType, HeaderEncV0); // encrypt 对应 V0
}
TEST_F(CheckHeadMultiTest, UnrecognizedHeader) {
char header[MIN_COMLEN + 4] = { 0xFF, 0xFE, 0xFD, 0xFC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
HeaderEncType encType;
FlagType type = CheckHeadMulti(header, encType);
EXPECT_EQ(type, FLAG_UNKNOWN);
EXPECT_EQ(encType, HeaderEncUnknown);
}
// ============================================
// 头部生成和验证往返测试
// ============================================
class HeaderRoundTripTest : public ::testing::Test {};
TEST_F(HeaderRoundTripTest, DefaultEncryptRoundTrip) {
HeaderFlag hf = GetHead(default_encrypt, 0x42);
char buffer[MIN_COMLEN + 4] = {};
memcpy(buffer, hf.data(), FLAG_LENGTH);
HeaderEncType encType;
FlagType type = CheckHeadMulti(buffer, encType);
EXPECT_EQ(type, FLAG_HELL);
}
TEST_F(HeaderRoundTripTest, EncryptRoundTrip) {
HeaderFlag hf = GetHead(encrypt, 0x88);
char buffer[MIN_COMLEN + 4] = {};
memcpy(buffer, hf.data(), FLAG_LENGTH);
HeaderEncType encType;
FlagType type = CheckHeadMulti(buffer, encType);
EXPECT_EQ(type, FLAG_HELL);
}
TEST_F(HeaderRoundTripTest, AllKeyValuesRoundTrip) {
for (int key = 1; key < 256; ++key) {
HeaderFlag hf = GetHead(encrypt, static_cast<unsigned char>(key));
char buffer[MIN_COMLEN + 4] = {};
memcpy(buffer, hf.data(), FLAG_LENGTH);
HeaderEncType encType;
FlagType type = CheckHeadMulti(buffer, encType);
EXPECT_EQ(type, FLAG_HELL) << "Failed for key: " << key;
}
}
// ============================================
// 数据包长度字段测试
// ============================================
class PacketLengthTest : public ::testing::Test {};
#pragma pack(push, 1)
struct PacketHeader {
char flag[FLAG_LENGTH];
uint32_t packedLength; // 压缩后长度
uint32_t originalLength; // 原始长度
};
#pragma pack(pop)
TEST_F(PacketLengthTest, HeaderSize) {
EXPECT_EQ(sizeof(PacketHeader), HDR_LENGTH);
}
TEST_F(PacketLengthTest, BuildAndParsePacket) {
PacketHeader pkt = {};
memcpy(pkt.flag, "HELL", 4);
pkt.flag[6] = 0x42;
pkt.flag[7] = ~0x42;
pkt.packedLength = 100;
pkt.originalLength = 200;
// 解析
uint32_t packedLen, origLen;
memcpy(&packedLen, reinterpret_cast<char*>(&pkt) + FLAG_LENGTH, sizeof(uint32_t));
memcpy(&origLen, reinterpret_cast<char*>(&pkt) + FLAG_LENGTH + sizeof(uint32_t), sizeof(uint32_t));
EXPECT_EQ(packedLen, 100u);
EXPECT_EQ(origLen, 200u);
}
TEST_F(PacketLengthTest, TotalPacketLength) {
// 总包长度 = HDR_LENGTH + 压缩数据长度
uint32_t dataLen = 1000;
uint32_t totalLen = HDR_LENGTH + dataLen;
EXPECT_EQ(totalLen, 1016u);
}
// ============================================
// 边界条件测试
// ============================================
class HeaderBoundaryTest : public ::testing::Test {};
TEST_F(HeaderBoundaryTest, MinimalPacket) {
// 最小合法包:只有头部
std::vector<uint8_t> packet(HDR_LENGTH);
memcpy(packet.data(), "HELL", 4);
packet[6] = 0x42;
packet[7] = ~0x42;
// packedLength = HDR_LENGTH
uint32_t packedLen = HDR_LENGTH;
memcpy(packet.data() + FLAG_LENGTH, &packedLen, sizeof(uint32_t));
// originalLength = 0
uint32_t origLen = 0;
memcpy(packet.data() + FLAG_LENGTH + sizeof(uint32_t), &origLen, sizeof(uint32_t));
EXPECT_EQ(packet.size(), HDR_LENGTH);
}
TEST_F(HeaderBoundaryTest, MaxPacketLength) {
// 验证大包长度字段
uint32_t maxDataLen = 100 * 1024 * 1024; // 100 MB
uint32_t totalLen = HDR_LENGTH + maxDataLen;
PacketHeader pkt = {};
pkt.packedLength = totalLen;
pkt.originalLength = maxDataLen * 2; // 压缩前更大
EXPECT_EQ(pkt.packedLength, totalLen);
EXPECT_EQ(pkt.originalLength, maxDataLen * 2);
}
TEST_F(HeaderBoundaryTest, TruncatedHeader) {
// 不完整的头部不应该被识别
char truncated[4] = { 'H', 'E', 'L', 'L' };
// 不足以进行完整验证
// 这里只是验证常量定义正确
EXPECT_LT(sizeof(truncated), static_cast<size_t>(MIN_COMLEN));
}
// ============================================
// FlagType 枚举测试
// ============================================
class FlagTypeTest : public ::testing::Test {};
TEST_F(FlagTypeTest, EnumValues) {
EXPECT_EQ(FLAG_WINOS, -1);
EXPECT_EQ(FLAG_UNKNOWN, 0);
EXPECT_EQ(FLAG_SHINE, 1);
EXPECT_EQ(FLAG_FUCK, 2);
EXPECT_EQ(FLAG_HELLO, 3);
EXPECT_EQ(FLAG_HELL, 4);
}
TEST_F(FlagTypeTest, HeaderEncTypeValues) {
EXPECT_EQ(HeaderEncUnknown, -1);
EXPECT_EQ(HeaderEncNone, 0);
EXPECT_EQ(HeaderEncV0, 1);
EXPECT_EQ(HeaderEncNum, 8);
}