Added a constexpr string obfuscator
This commit is contained in:
parent
952c4bf489
commit
f359800ce5
@ -121,6 +121,7 @@ set(HEADER_FILES
|
||||
src/misc/hex.h
|
||||
src/misc/advanced_mutex.h
|
||||
src/misc/memtracker.h
|
||||
src/misc/strobf.h
|
||||
|
||||
src/log/translation.h
|
||||
src/log/LogUtils.h
|
||||
|
144
src/misc/strobf.h
Normal file
144
src/misc/strobf.h
Normal file
@ -0,0 +1,144 @@
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <array>
|
||||
#include <string_view>
|
||||
#include <iostream>
|
||||
|
||||
namespace str_obf {
|
||||
namespace internal {
|
||||
template <typename char_t, size_t size, typename key_t>
|
||||
struct message {
|
||||
/* helper to access the types */
|
||||
static constexpr auto _size = size;
|
||||
using _char_t = char_t;
|
||||
using _key_t = key_t;
|
||||
|
||||
/* memory */
|
||||
std::array<char_t, size> buffer{0};
|
||||
key_t key{};
|
||||
|
||||
/* some memory access helpers */
|
||||
std::string_view string_view() const noexcept { return {this->buffer.begin(), this->length}; }
|
||||
std::string string() const { return {this->buffer.begin(), this->length}; }
|
||||
const char* c_str() const noexcept { return &this->buffer[0]; }
|
||||
};
|
||||
|
||||
constexpr auto time_seed() noexcept {
|
||||
std::uint64_t shifted = 0;
|
||||
|
||||
for( const auto c : __TIME__ )
|
||||
{
|
||||
shifted <<= 8;
|
||||
shifted |= c;
|
||||
}
|
||||
|
||||
return shifted;
|
||||
}
|
||||
|
||||
constexpr uint64_t string_hash(const char* str, int h = 0) noexcept {
|
||||
return !str[h] ? 5381 : (string_hash(str, h + 1) * 33) ^ str[h];
|
||||
}
|
||||
|
||||
constexpr std::uint32_t rng32_next(std::uint64_t& state, const std::uint32_t& inc) noexcept {
|
||||
std::uint64_t oldstate = state;
|
||||
// Advance internal state
|
||||
state = oldstate * 6364136223846793005ULL + (inc | 1UL);
|
||||
// Calculate output function (XSH RR), uses old state for max ILP
|
||||
std::uint32_t xorshifted = ((oldstate >> 18u) ^ oldstate) >> 27u;
|
||||
std::uint32_t rot = oldstate >> 59u;
|
||||
return (xorshifted >> rot) | (xorshifted << ((-rot) & 31));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename char_t, typename key_t>
|
||||
constexpr inline void crypt(char_t* begin, size_t length, const key_t& key) noexcept {
|
||||
static_assert(sizeof(char_t) == 1, "Currently only 8 bit supported");
|
||||
if(length == 0) return;
|
||||
|
||||
auto kbegin = std::begin(key);
|
||||
auto kend = std::end(key);
|
||||
if(kbegin == kend) return;
|
||||
|
||||
auto it = kbegin;
|
||||
while(length-- > 0) {
|
||||
if(it == kend)
|
||||
it = kbegin;
|
||||
|
||||
*begin ^= *it;
|
||||
|
||||
it++;
|
||||
begin++;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename char_t, size_t message_size, typename key_t>
|
||||
constexpr inline internal::message<char_t, message_size, key_t> encode(const char_t(&message)[message_size], const key_t& key) noexcept {
|
||||
internal::message<char_t, message_size, key_t> result{};
|
||||
result.key = key;
|
||||
|
||||
{
|
||||
auto bit = result.buffer.begin();
|
||||
auto mit = message;
|
||||
|
||||
size_t index = message_size;
|
||||
while(index-- > 0)
|
||||
*bit++ = *mit++;
|
||||
}
|
||||
|
||||
crypt(result.buffer.data(), message_size, key);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename char_t, size_t message_size, typename key_t>
|
||||
inline std::string decode(const internal::message<char_t, message_size, key_t>& message) {
|
||||
std::string result{};
|
||||
result.resize(message_size);
|
||||
|
||||
memcpy(result.data(), message.buffer.begin(), message_size);
|
||||
crypt(result.data(), message_size, message.key);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
constexpr inline std::array<uint8_t, 16> generate_key(const char* _str_seed, unsigned int line) noexcept {
|
||||
std::uint64_t rng_seed = internal::time_seed() ^ internal::string_hash(_str_seed, 0) ^ line;
|
||||
std::uint64_t rng_base = rng_seed;
|
||||
|
||||
std::array<uint8_t, 16> result{};
|
||||
for(auto& it : result)
|
||||
it = (internal::rng32_next(rng_base, rng_seed) >> 16UL) & 0xFFUL;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename message>
|
||||
struct decode_helper {
|
||||
const message& encoded;
|
||||
std::array<typename message::_char_t, message::_size + 1> buffer{0};
|
||||
bool decoded = false; /* a trivial check which (if this only gets used once) the compiler could evaluate */
|
||||
|
||||
#ifndef WIN32 /* else if you call string_view() or string() it wound inline this method */
|
||||
__attribute__((always_inline))
|
||||
#endif
|
||||
const char* c_str() noexcept {
|
||||
if(!this->decoded) {
|
||||
memcpy(this->buffer.data(), this->encoded.buffer.begin(), message::_size);
|
||||
crypt((typename message::_char_t*) this->buffer.data(), message::_size, this->encoded.key);
|
||||
buffer[message::_size] = 0; /* append the null terminator at the end */
|
||||
this->decoded = true; /* let the compiler combine buffer[message::_size] and this->decoded = true; */
|
||||
}
|
||||
|
||||
return &this->buffer[0];
|
||||
}
|
||||
|
||||
inline std::string_view string_view() noexcept {
|
||||
return {this->c_str(), message::_size};
|
||||
}
|
||||
|
||||
inline std::string string() { return {this->c_str(), message::_size}; }
|
||||
};
|
||||
}
|
||||
|
||||
#define strobf_define(variable_name, string) \
|
||||
constexpr const auto variable_name = ::str_obf::encode(string, str_obf::generate_key(__FILE__ __TIME__, __LINE__))
|
||||
|
||||
#define strobf_val(variable_name) (str_obf::decode_helper<decltype(_hello_world)>{_hello_world})
|
Loading…
Reference in New Issue
Block a user