libpromeki main
PROfessional MEdia toolKIt
 
Loading...
Searching...
No Matches
obfuscatedstring.h
Go to the documentation of this file.
1
8#pragma once
9
10#include <cstddef>
11#include <cstdint>
13#include <promeki/core/string.h>
14#include <promeki/core/fnv1a.h>
15
17
40template <size_t N, uint64_t Seed>
42 public:
52 consteval ObfuscatedString(const char (&str)[N]) : _data{} {
53 uint64_t state = initState();
54 for (size_t i = 0; i < N - 1; ++i) {
55 uint64_t key = keyAt(i);
56 unsigned char k0 = static_cast<unsigned char>(key);
57 unsigned char k1 = static_cast<unsigned char>(key >> 8);
58 unsigned char c = static_cast<unsigned char>(str[i]);
59
60 // Round 1: XOR with position-derived key byte.
61 c ^= k0;
62 // Round 2: modular add of CBC state byte.
63 c = static_cast<unsigned char>(c + static_cast<unsigned char>(state));
64 // Round 3: rotate left by 1-7 bits (derived from second key byte).
65 unsigned shift = (k1 & 0x07) | 1;
66 c = static_cast<unsigned char>((c << shift) | (c >> (8 - shift)));
67 // Round 4: XOR with second key byte.
68 c ^= k1;
69
70 _data[i] = static_cast<char>(c);
71 state = advanceState(state, c, key);
72 }
73 }
74
79 String decode() const {
80 String out(N - 1, '\0');
81 uint64_t state = initState();
82 for (size_t i = 0; i < N - 1; ++i) {
83 uint64_t key = keyAt(i);
84 unsigned char k0 = static_cast<unsigned char>(key);
85 unsigned char k1 = static_cast<unsigned char>(key >> 8);
86 unsigned char c = static_cast<unsigned char>(_data[i]);
87
88 // Undo round 4: XOR with second key byte.
89 c ^= k1;
90 // Undo round 3: rotate right.
91 unsigned shift = (k1 & 0x07) | 1;
92 c = static_cast<unsigned char>((c >> shift) | (c << (8 - shift)));
93 // Undo round 2: subtract CBC state byte.
94 c = static_cast<unsigned char>(c - static_cast<unsigned char>(state));
95 // Undo round 1: XOR.
96 c ^= k0;
97
98 out.setCharAt(i, Char(static_cast<char>(c)));
99 state = advanceState(state, static_cast<unsigned char>(_data[i]), key);
100 }
101 return out;
102 }
103
108 operator String() const { return decode(); }
109
110 private:
111 // Initial 64-bit CBC state derived from the full seed.
112 static constexpr uint64_t initState() {
113 uint64_t h = Seed * 0xbf58476d1ce4e5b9ULL;
114 h ^= h >> 31;
115 h *= 0x94d049bb133111ebULL;
116 h ^= h >> 31;
117 return h;
118 }
119
120 // Per-byte 64-bit key derived from Seed and position (splitmix64 finalizer).
121 static constexpr uint64_t keyAt(size_t i) {
122 uint64_t h = (Seed ^ (static_cast<uint64_t>(i) * 0x9e3779b97f4a7c15ULL)) *
123 0xbf58476d1ce4e5b9ULL;
124 h ^= h >> 31;
125 h *= 0x94d049bb133111ebULL;
126 h ^= h >> 31;
127 return h;
128 }
129
130 // Advance the 64-bit CBC state using ciphertext and key.
131 static constexpr uint64_t advanceState(uint64_t state, unsigned char cipher, uint64_t key) {
132 state ^= static_cast<uint64_t>(cipher) | (key << 8);
133 state *= 0x517cc1b727220a95ULL;
134 state ^= state >> 29;
135 return state;
136 }
137
138 char _data[N - 1];
139};
140
142
143// NOLINTNEXTLINE(bugprone-macro-parentheses)
144
149#define PROMEKI_OBFUSCATE_SEED \
150 (::promeki::fnv1a(__FILE__) ^ (static_cast<uint64_t>(__LINE__) * 0x9e3779b97f4a7c15ULL) ^ \
151 ::promeki::fnv1a(__DATE__ __TIME__))
152
162// NOLINTNEXTLINE(bugprone-macro-parentheses)
163#define PROMEKI_OBFUSCATE(str) \
164 ([]() { \
165 static constexpr auto _obf = \
166 ::promeki::ObfuscatedString<sizeof(str), PROMEKI_OBFUSCATE_SEED>(str); \
167 return _obf.decode(); \
168 }())
Unicode-aware character class wrapping a single codepoint.
Definition char.h:23
Dynamic array container wrapping std::vector.
Definition list.h:40
Compile-time string obfuscation.
Definition obfuscatedstring.h:41
String decode() const
Decodes the obfuscated data back to the original string.
Definition obfuscatedstring.h:79
consteval ObfuscatedString(const char(&str)[N])
Encodes a string literal at compile time.
Definition obfuscatedstring.h:52
Encoding-aware string class with copy-on-write semantics.
Definition string.h:35
#define PROMEKI_NAMESPACE_BEGIN
Starts a promeki namespace block.
Definition namespace.h:14
#define PROMEKI_NAMESPACE_END
Ends a promeki namespace block.
Definition namespace.h:19