JustasMasiulis / xorstr

heavily vectorized c++17 compile time string encryption.
Apache License 2.0
1.19k stars 193 forks source link

limit of 100 characters #13

Closed Kukunin closed 5 years ago

Kukunin commented 5 years ago

Hey. First of all, thanks for the great project.

I get an error on not-so-long strings (more than 100 characters), the static_assert fails.

How is it hard to fix this? Is it a flaw of design or a limitation of implementation?

Thanks

JustasMasiulis commented 5 years ago

It's not a flaw by itself as I had decided to simply use 100 characters as a default limit to reduce load on compiler, however the missing conditional support for it can indeed be seen as one.

The maximum length of string is essentially decided here. All this does is generate c_at<0>(str), c_at<1>(str), ..., c_at<99>(str).

Possible solutions:

I'll add an opt-in setting using #define to allow for longer strings. One thing that would be nice to know is what would your strings maximum length be?

Kukunin commented 5 years ago

Thanks for the quick answer. I understood the mechanic. Can you give, please, more info about why is it required to split a string into a sequence of c_at<0>(str), c_at<1>(str), ..., c_at<99>(str)? is it to avoid putting encoded data into .rdata section? or do avoid compiler optimizations?

As for the length, I don't know. 100 seems ok really, but the limit itself surprised me. In my application, I extensively trying to hide string literals, so I encode almost any string. Some of them, such as long log reports, or configs are longer than 100.

I tried https://github.com/adamyaxley/Obfuscate that works well on strings of any length, but it uses a fixed constant char as XOR key, which confuses me.

Kukunin commented 5 years ago

I can actually work around the limit by splitting the original big string on smaller, and then concat them into one std::string

JustasMasiulis commented 5 years ago

It is used in the process of storing string character into a type.

Not getting the strings/keys into RDATA has more to do with adding volatile to the buffers (clang, gcc) and not using initializer lists while instead unrolling assignments in some other fashion like recursion, c++17 folds or some other means like using std::index_sequence.

Concerning the key - it should be different for every translation unit as it is generated from the hash of __TIME__ macro.

I'll be adding the option to increase the max tomorrow. As a temporary fix you can add XORSTR_STRING_EXPAND_10(10, x), XORSTR_STRING_EXPAND_10(11, x), ... to the XORSTR_STRING_EXPAND_100 macro until you reach the desired length and then edit the static_assert.

An important thing to note is that you might want to turn off AVX intrinsics if you don't know what processors will be running the software.

Kukunin commented 5 years ago

Thanks for the explanation. That's helpful

JustasMasiulis commented 5 years ago

Should have fixed it. There is no need to change anything / opt in as I decided that changing the method is a slightly better choice compared to adding more of those expand macros.

Kukunin commented 5 years ago

Amazing!! you rock