Constexpr Encrypted Strings

0

I tried writing a simple constexpr based string encryption class, but the problem was that it did not work.

Then, when going online I found source codes that did very weird things such as:

////////////////////////////////////////////////////////////////////
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)
////////////////////////////////////////////////////////////////////

My question is, what is with alll those IndexList-related templates? Why is there so many of them and what is their purpose? Also, why does the code above work, but the one below (My attempt) not?

Checked both in IDA, mine is always still visible.

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++11
templates
constexpr
asked on Stack Overflow Nov 21, 2020 by Carol Victor

1 Answer

1

From what I can see, your string is required to be in your executable. This is a classical mistake with constexpr where one assumes that adding constexpr to the functions results in execution at compile time. Spoiler: it doesn't.

If you want a variable to be calculated at compile time, you need to put constexpr in front of it. (Or constinit if available)

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

This should result in b being calculated at compile time, however a could still be there. Since you ain't using it, your compiler will most likely remove it if optimizations are enabled.

Personally I would try to write the following:

constexpr encstr b {"testtesttest"};

It could be that this doesn't compile as you are accepting mutable strings in your constructor. Try adding an extra const

answered on Stack Overflow Nov 21, 2020 by JVApen

User contributions licensed under CC BY-SA 3.0