Обфускация std::string во время компиляции

Я пытаюсь написать функцию для скрытия (обфускации) текстовых строк во время компиляции в двоичном коде. Назначение: отключить удобный поиск и модифицировать текстовые сообщения с помощью бинарного редактора.

Алгоритм прост: преобразовать символы в строке в deltas, т.е. е. строка abcd должна быть сохранена в двоичном файле как a\001\001\001.

Я написал следующий код, он работает:

#include <string>
#include <stdio.h>
#include <string.h>

constexpr std::string str_encrypt(const char *str) {
    std::string rc; 
    unsigned char x = 0, c;
    while(c = *str++) {
         rc.push_back(c - x); 
        x = c;
    }   
    return rc; 
}

std::string str_decrypt(const std::string &str) {
    std::string rc; 
    unsigned char x = 0;
    for(unsigned char c : str)
        rc.push_back(x += c); 
    return rc; 
}

const std::string hello(str_encrypt("Hello, world!"));

int main(int argc, char **argv) {
    for(unsigned char c : hello)
        printf("%d ", c); 
    putchar('\n');
    printf("S=[%s]\n", str_decrypt(hello).c_str());
    return 0;
}

Но строка все еще не "зашифрована" в двоичном файле:

$ c++ -std=c++2b -O2 constexpr.cpp  && strings a.out | grep Hello
Hello, world!

Когда я меняю constexpr на consteval, я вижу ошибку компиляции:

$ c++ -std=c++2b -O2 constexpr.cpp 
constexpr.cpp:23:36: error: ‘std::string{std::__cxx11::basic_string<char>::_Alloc_hider{((char*)(&<anonymous>.std::__cxx11::basic_string<char>::<anonymous>.std::__cxx11::basic_string<char>::<unnamed union>::_M_local_buf))}, 13, std::__cxx11::basic_string<char>::<unnamed union>{char [16]{'H', '\035', '\007', '\000', '\003', '\37777777675', '\37777777764', 'W', '\37777777770', '\003', '\37777777772', '\37777777770', '\37777777675', 0}}}’ is not a constant expression
   23 | const std::string hello(str_encrypt("Hello, world!"));

Мой вопрос: Можно ли написать такое шифрование во время компиляции? Если да, то подскажите, как быть.

Мой компилятор: g++ (GCC) 12.2.1 20230201

Если вы не хотите заново изобретать завещание, вы можете использовать github.com/JustasMasiulis/xorstr

Dark Sorrow 16.05.2023 06:24

Взгляните и на это: stackoverflow.com/questions/32287125/…

Pepijn Kramer 16.05.2023 07:04
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
2
98
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблема в том, что str_encrypt не оценивается во время компиляции.

Когда я меняю constexpr на consteval, я вижу ошибку компиляции

Это подсказка, когда мы переключаемся на consteval, который требует, чтобы str_encrypt была функцией немедленного/времени компиляции, компилятор выдает ошибку.

Начиная с C++20, std::string можно использовать в контексте времени компиляции, если это временное выделение, т. е. строка должна быть уничтожена перед выходом из контекста времени компиляции.

В этом примере это не так, поэтому str_encrypt не может быть функцией времени компиляции.

Если бы мы поставили:

constexpr std::string hello(str_encrypt("Hello, world!"));

Тогда мы увидим ту же ошибку, что и при использовании consteval на str_encrypt.

Однако массивы или std::arrays могут быть constexpr.

Поэтому, если вместо возврата std::string мы вернем std::array, то пример может работать так, как ожидалось.

Этот модифицированный пример работает с g++ / clang++ и требует C++17. Было бы целесообразно использовать consteval для принудительной оценки времени компиляции, но, конечно, требуется C++20.

#include <string>
#include <stdio.h>
#include <string.h>
#include <array>

template <size_t N>
constexpr std::array<char, N> str_encrypt(const char (&str)[N]) {
    std::array<char, N> output{};
    unsigned char x = 0, c = 0;

    for (int i = 0; i < N; ++i) {
        c = str[i];
        output[i] = (c - x);
        x = c;
    }
    return output;
}

template <size_t N>
std::string str_decrypt(const std::array<char, N> &str) {
    std::string rc;
    unsigned char x = 0;
    for(unsigned char c : str)
        rc.push_back(x += c);
    return rc;
}

constexpr auto hello = str_encrypt("Hello, world!");

int main(int argc, char **argv) {
    for(unsigned char c : hello)
        printf("%d ", c);
    putchar('\n');
    printf("S=[%s]\n", str_decrypt(hello).c_str());
    return 0;
}

Выход:

$ ./example
72 29 7 0 3 189 244 87 248 3 250 248 189 223
S=[Hello, world!]

Строка «Привет, мир!» не находится в двоичном формате, как и функция str_encrypt.

$ strings example | grep Hello

$ objdump -t -C example | grep str_
0000000000001302  w    F .text  00000000000000a6              std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > str_decrypt<14ul>(std::array<char, 14ul> const&)

Годболт: https://godbolt.org/z/vPj3bW6Yz

Другие вопросы по теме