首页 > 解决方案 > Consexpr 加密字符串

问题描述

我尝试编写一个简单的基于 constexpr 的字符串加密类,但问题是它不起作用。

然后,当我上网时,我发现了一些非常奇怪的源代码,例如:

////////////////////////////////////////////////////////////////////
template <int X> struct EnsureCompileTime {
    enum : int {
        Value = X
    };
};
////////////////////////////////////////////////////////////////////
 
 
////////////////////////////////////////////////////////////////////
//Use Compile-Time as seed
#define Seed ((__TIME__[7] - '0') * 1  + (__TIME__[6] - '0') * 10  + \
              (__TIME__[4] - '0') * 60   + (__TIME__[3] - '0') * 600 + \
              (__TIME__[1] - '0') * 3600 + (__TIME__[0] - '0') * 36000)
////////////////////////////////////////////////////////////////////
 
 
////////////////////////////////////////////////////////////////////
constexpr int LinearCongruentGenerator(int Rounds) {
    return 1013904223 + 1664525 * ((Rounds> 0) ? LinearCongruentGenerator(Rounds - 1) : Seed & 0xFFFFFFFF);
}
#define Random() EnsureCompileTime<LinearCongruentGenerator(10)>::Value //10 Rounds
#define RandomNumber(Min, Max) (Min + (Random() % (Max - Min + 1)))
////////////////////////////////////////////////////////////////////
 
 
////////////////////////////////////////////////////////////////////
template <int... Pack> struct IndexList {};
////////////////////////////////////////////////////////////////////
 
 
////////////////////////////////////////////////////////////////////
template <typename IndexList, int Right> struct Append;
template <int... Left, int Right> struct Append<IndexList<Left...>, Right> {
    typedef IndexList<Left..., Right> Result;
};
////////////////////////////////////////////////////////////////////
 
 
////////////////////////////////////////////////////////////////////
template <int N> struct ConstructIndexList {
    typedef typename Append<typename ConstructIndexList<N - 1>::Result, N - 1>::Result Result;
};
template <> struct ConstructIndexList<0> {
    typedef IndexList<> Result;
};
////////////////////////////////////////////////////////////////////
 
 
////////////////////////////////////////////////////////////////////
const char XORKEY = static_cast<char>(RandomNumber(0, 0xFF));
constexpr char EncryptCharacter(const char Character, int Index) {
    return Character ^ (XORKEY + Index);
}
 
template <typename IndexList> class CXorString;
template <int... Index> class CXorString<IndexList<Index...> > {
private:
    char Value[sizeof...(Index) + 1];
public:
    constexpr CXorString(const char* const String)
    : Value{ EncryptCharacter(String[Index], Index)... } {}
 
    char* decrypt() {
        for(int t = 0; t < sizeof...(Index); t++) {
            Value[t] = Value[t] ^ (XORKEY + t);
        }
        Value[sizeof...(Index)] = '\0';
        return Value;
    }
 
    char* get() {
        return Value;
    }
};
#define XorS(X, String) CXorString<ConstructIndexList<sizeof(String)-1>::Result> X(String)
////////////////////////////////////////////////////////////////////

我的问题是,所有这些与 IndexList 相关的模板是什么?为什么会有这么多,他们的目的是什么?另外,为什么上面的代码有效,但下面的代码(我的尝试)无效?

在 IDA 中检查了两者,我的始终仍然可见。

class encstr {
private:
    char m_buff[200];
    int m_len;
public:
    template<int len>
    constexpr encstr(char(&str)[len]) : m_len(len - 1) {
        for (int i = 0; i < m_len; ++i) {
            m_buff[i] = str[i] ^ 0x20; // any key
            str[i] = '\0';
        }
    }
    ~encstr() = default;
    char* dec() {
        char* r = (char*)malloc(m_len+1);
        for (int i = 0; i < m_len; ++i) {
            r[i] = m_buff[i] ^ 0x20;
        }
        r[m_len + 1] = '\0';
        return r;
    }
};

int main()
{
   char a[] = {"testtesttest"};
   encstr b = a;
   char* c = b.dec();
   printf("%s\n", c);
   getchar();
}

标签: c++c++11templatesconstexpr

解决方案


据我所知,您的字符串必须在您的可执行文件中。这是 constexpr 的一个经典错误,其中假设将 constexpr 添加到函数会导致在编译时执行。剧透:它没有。

如果你想在编译时计算一个变量,你需要把 constexpr 放在它前面。(或 constinit 如果可用)

constexpr char a[] = {"testtesttest"};
constexpr encstr b = a;

这应该会导致在编译时计算 b,但是 a 可能仍然存在。由于您没有使用它,因此如果启用了优化,您的编译器很可能会删除它。

我个人会尝试编写以下内容:

constexpr encstr b {"testtesttest"};

这可能是因为您在构造函数中接受可变字符串,因此无法编译。尝试添加一个额外的 const


推荐阅读