I want to have a compile-time string encryption, such that I could write in my code:
const auto encryptedInvalidLicense = ENCRYPT("Invalid license");
std::cout << encryptedInvalidLicense.decrypt() << std::endl; // outputs "Invalid license"
and the string "Invalid license" wont appear in the binaries.
Pre-builds might be the answer, but I'm looking for a pure c++ constexpr
solution to this problem, and that it will be supported by VS2015.
Any suggestions?
I've already looked into Compile-time string encryption, which doesn't provide a constexpr solution to the problem.
I've also looked into http://www.unknowncheats.me/forum/c-and-c/113715-compile-time-string-encryption.html . Though it's a constexpr solution, VS2015 still adds the strings plain text to the binaries.
Here's how I would do it:
1.) Use the
str_const
template for constexpr string manipulation described here: Conveniently Declaring Compile-Time Strings in C++Code:
This lets you do things like
str_const message = "Invalid license"
and manipulatemessage
in constexpr functions.2.) Make a simple compile-time pseudorandom generator, using the macros
__TIME__
and__LINE__
to generate the seed. This is described in detail here: Generate random numbers in C++ at compile timeThey give some template-based code.
3.) Make a struct, with a
constexpr
ctor which takes eitherconst char []
and templates itself against the size similarly to thestr_const
example, or which just takes astr_const
, and generates twostr_const
which it are its member variables.str_const
of lengthn
containing pseudorandom unsigned chars, generated using the pseudorandom generator, wheren
is the length of the input. (the "noise string")str_const
of lengthn
containing the entry-wise sum (as unsigned chars) of the input characters with the noise characters. (the "cipher text")Then it has a member function
decrypt
which need not be constexpr, and can return astd::string
, which simply subtracts each character of the noise string from the corresponding character of the cipher text and returns the resulting string.If your compiler is still storing the original string literal in the binary, it means that either it's storing the input string literal (the constructor argument) which I don't think it should be doing since its a temporary, or its basically inlining the
decrypt
function, and you should be able to prevent that by obfuscating it with function pointers, or marking itvolatile
or similar.Edit: I'm not sure if the standard requires that temporary constexpr objects should not appear in the binary. Actually I'm curious about that now. My expectation is that at least in a release build, a good compiler should remove them when they are no longer needed.
Edit: So, you already accepted my answer. But anyways for completeness, here's some source code that implements the above ideas, using only C++11 standard. It works on gcc-4.9 and clang-3.6, even when optimizations are disabled, as nearly as I can tell.
I'd have code like this:
Not trying to be clever. Copy the #if code in a separate file, compile and run, paste the result back.