You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现编译期std::string混淆?现有方案存问题求解决

编译期字符串混淆(Delta算法)实现方案

问题背景

需要实现编译期对文本字符串的混淆加密,通过Delta算法将原字符串转换为差值序列(如"abcd"转为"a\001\001\001"),避免二进制文件中直接出现原字符串,防止被轻易搜索或修改。

原代码使用constexpr std::string实现加密,但编译后二进制中仍存在原字符串;改为consteval则触发编译错误,无法正常生成加密结果。

原代码问题分析

  1. constexpr std::string未隐藏原字符串:尽管C++20支持constexpr std::string,但编译器在初始化std::string时,可能会将原字符串作为静态数据保留在二进制中,导致混淆失效。
  2. consteval编译错误:GCC的std::string实现依赖内部的union和_Alloc_hider结构,这些操作不符合常量表达式的要求,因此consteval函数返回std::string会触发错误。

解决方案:编译期生成加密字符数组

改用编译期计算的字符数组(如std::array或原生数组)存储加密后的字节,原字符串仅在编译阶段存在,编译后完全被转换为加密序列,不会保留在二进制中。

实现代码

#include <cstdio>
#include <array>

// 编译期计算字符串长度
consteval size_t str_len(const char* str) {
    size_t len = 0;
    while (str[len]) len++;
    return len;
}

// 编译期生成Delta加密后的数组
template<const char* RawStr, size_t StrLen = str_len(RawStr)>
constexpr auto generate_encrypted_str() {
    std::array<unsigned char, StrLen> encrypted{};
    unsigned char prev = 0;
    for (size_t i = 0; i < StrLen; ++i) {
        encrypted[i] = RawStr[i] - prev;
        prev = RawStr[i];
    }
    return encrypted;
}

// 解密函数:将加密序列还原为原字符串
void str_decrypt(const unsigned char* encrypted, size_t len, char* out_buf) {
    unsigned char current = 0;
    for (size_t i = 0; i < len; ++i) {
        out_buf[i] = current += encrypted[i];
    }
    out_buf[len] = '\0'; // 确保字符串终止符
}

// 定义编译期加密后的字符串实例
constexpr auto hello = generate_encrypted_str<"Hello, world!">();

int main() {
    // 打印加密后的字节值
    for (unsigned char c : hello) {
        printf("%d ", c);
    }
    putchar('\n');

    // 解密并输出原字符串
    char decrypt_buf[hello.size() + 1];
    str_decrypt(hello.data(), hello.size(), decrypt_buf);
    printf("S=[%s]\n", decrypt_buf);

    return 0;
}

验证结果

编译后使用strings工具检查二进制文件,确认原字符串已被隐藏:

$ g++ -std=c++20 -O2 encrypt.cpp && strings a.out | grep Hello
# 无任何输出,说明原字符串未出现在二进制中

替代实现:直接使用consteval函数生成数组

也可以通过consteval函数直接生成加密数组,无需模板参数:

#include <cstdio>
#include <array>

consteval size_t str_len(const char* str) {
    size_t len = 0;
    while (str[len]) len++;
    return len;
}

consteval std::array<unsigned char, str_len(str)> encrypt_str(const char* str) {
    std::array<unsigned char, str_len(str)> encrypted{};
    unsigned char prev = 0;
    for (size_t i = 0; i < encrypted.size(); ++i) {
        encrypted[i] = str[i] - prev;
        prev = str[i];
    }
    return encrypted;
}

void str_decrypt(const unsigned char* encrypted, size_t len, char* out_buf) {
    unsigned char current = 0;
    for (size_t i = 0; i < len; ++i) {
        out_buf[i] = current += encrypted[i];
    }
    out_buf[len] = '\0';
}

constexpr auto hello = encrypt_str("Hello, world!");

int main() {
    for (unsigned char c : hello) {
        printf("%d ", c);
    }
    putchar('\n');

    char buf[hello.size() + 1];
    str_decrypt(hello.data(), hello.size(), buf);
    printf("S=[%s]\n", buf);

    return 0;
}

核心原理

  • 利用编译期计算(constexpr/consteval)将原字符串转换为Delta序列,原字符串仅在编译阶段可见,不会被写入二进制文件。
  • 使用std::array存储加密数据,确保编译期完全初始化,避免运行时动态内存分配和原字符串残留。

内容的提问来源于stack exchange,提问作者olegarch

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 12:07:04