Reputation: 13002
Is there a way to create hash values to strings, or encrypted strings, at compile time? I want to put the raw string that generates the encrypted text or hash values directly in my code as a string literal, but I don't want them to be compiled into the executable in their untransformed form.
Something like this?
constexpr uint32 hash(const char * string){
... // turns a string into a value to represent it
}
constexpr std::string encrypt(const char * string){
... // turns a string into a cyphertext (unsure what return type would work best here)
}
void f(){
std::string input << std::cin();
switch(hashedKey){
case hash("help"): // legal?
if(0 == encryptRT(input).compare(encrypt("secret string")){
// the secret string should never appear in the executable
}
break;
}
}
It's very important that the strings put directly into the constexpr functions never be put into the string table. Is this possible?
Upvotes: 2
Views: 400
Reputation: 37549
Example of compile-time xor
obfuscation:
#include <iostream>
#include <iomanip>
#include <cstddef>
#include <cstdint>
#include <array>
template<::std::size_t x_data_bytes_count, ::std::size_t x_key_bytes_count> constexpr auto
obfuscate
(
::std::array<::std::uint8_t, x_data_bytes_count> const & input
, ::std::array<::std::uint8_t, x_key_bytes_count> const & key
) noexcept
{
static_assert(::std::size_t{0} < x_data_bytes_count);
// Assuming null-terminated string is used as a key.
static_assert(::std::size_t{1} < x_key_bytes_count);
::std::array<::std::uint8_t, x_data_bytes_count> output{};
::std::size_t data_byte_index{};
::std::size_t key_byte_index{};
do
{
output[data_byte_index] = input[data_byte_index] xor key[key_byte_index];
data_byte_index = data_byte_index + ::std::size_t{1};
key_byte_index = key_byte_index + ::std::size_t{1};
key_byte_index = key_byte_index % (key.size() - ::std::size_t{1});
}
while(input.size() != data_byte_index);
return output;
}
// Following two overloads may accept string literals
// so calling obfuscation function would be more convenient.
template<::std::size_t x_data_bytes_count, ::std::size_t x_key_bytes_count> constexpr auto
obfuscate
(
char const ( & input )[x_data_bytes_count]
, char const ( & key )[x_key_bytes_count]
) noexcept
{
::std::size_t byte_index{};
::std::array<::std::uint8_t, x_data_bytes_count> input_arr{};
for(byte_index = 0; x_data_bytes_count != byte_index; ++byte_index)
{
input_arr[byte_index] = static_cast<::std::uint8_t>(input[byte_index]);
}
::std::array<::std::uint8_t, x_key_bytes_count> key_arr{};
for(byte_index = 0; x_key_bytes_count != byte_index; ++byte_index)
{
key_arr[byte_index] = static_cast<::std::uint8_t>(key[byte_index]);
}
return obfuscate(input_arr, key_arr);
}
template<::std::size_t x_data_bytes_count, ::std::size_t x_key_bytes_count> constexpr auto
obfuscate
(
::std::array<::std::uint8_t, x_data_bytes_count> const & input_arr
, char const ( & key )[x_key_bytes_count]
) noexcept
{
::std::size_t byte_index{};
::std::array<::std::uint8_t, x_key_bytes_count> key_arr{};
for(byte_index = 0; x_key_bytes_count != byte_index; ++byte_index)
{
key_arr[byte_index] = static_cast<::std::uint8_t>(key[byte_index]);
}
return obfuscate(input_arr, key_arr);
}
int main()
{
constexpr auto const & key{"Stack overflow"};
constexpr auto const obfuscated_str{obfuscate("Hello World!", key)};
for(auto const & ch: obfuscated_str)
{
::std::cout << ::std::hex << ::std::setw(2) << ::std::setfill('0')
<< static_cast<::std::uint32_t>(ch) << " ";
}
::std::cout << ::std::endl;
auto const deobfuscated_str{obfuscate(obfuscated_str, key)};
for(auto const & ch: deobfuscated_str)
{
::std::cout << ::std::hex << ::std::setw(2) << ::std::setfill('0')
<< static_cast<::std::uint32_t>(ch) << " ";
}
::std::cout << ::std::endl;
::std::cout << reinterpret_cast<char const *>(deobfuscated_str.data()) << ::std::endl;
return 0;
}
Upvotes: 5