В процессе разработки ПО для трейдинга столкнулся с тем, что программа должна иметь целую кучу файлов конфигурации, содержание которых хотелось бы скрыть от пользователя. Это могут быть настройки стратегий, параметры авторизации на сервере, текст для разных языков интерфейса и т.д.
Для файлов конфигурации я уже давно использую файлы с JSON. Очень удобная вещь. Осталось лишь добавить поддержку комментариев и зашифровать текст при помощи алгоритма AES. А для большей красоты еще и сжать текст перед шифровкой алгоритмом brotli.
Сказано — сделано. Встречайте — crypto-json, проект на гитхабе. Репозиторий содержит готовый редактор JSON с комментариями, который может также сохранить текст в зашифрованном виде. Настройки сжатия и шифрования можно задать перед сохранением файла и во время открытия. Также редактор позволяет сделать проверку JSON и может подсвечивать проблемные места.
Для использования зашифрованных файлов в программе библиотека содержит простые функции. Покажу пример кода, который раскрывает почти все возможности библиотеки:
#include <crypto-json/crypto-json.hpp> //... /* загрузим текст из файла test.json */ std::string src; crypto_json::load_file("test.json", src); /* настроим тип шифрования - алгоритм AES в режиме CFB, длина ключа 256 */ crypto_json::EncryptionAlgorithmType type = crypto_json::EncryptionAlgorithmType::USE_AES_CFB_256; /* создадим ключ и инициализирующий вектор длиной 256 */ std::array<uint8_t, 32> key; std::array<uint8_t, 32> iv; /* для примера, зададим случайный ключ и инициализирующий вектор */ crypto_json::generate_key_or_iv(key); crypto_json::generate_key_or_iv(iv); /* преобразуем ключ и инициализирующий вектор в hex-строку и выведем на экран */ std::cout << "key:" << std::endl << crypto_json::to_hex_string(key) << std::endl; std::cout << "iv:" << std::endl << crypto_json::to_hex_string(iv) << std::endl; /* преобразуем hex-строку в ключ и инициализирующий вектор */ std::array<uint8_t, 32> key2; std::array<uint8_t, 32> iv2; crypto_json::convert_hex_string_to_byte(crypto_json::to_hex_string(key), key2); crypto_json::convert_hex_string_to_byte(crypto_json::to_hex_string(iv), iv2); /* зашифруем текст и сожмьем его при помощи алгоритма brotli */ std::string crypto_json_str = crypto_json::to_crypto_json(src, key, iv, type, true); /* сравним размеры зашифрованного текста и оригинального */ std::cout << "src size:" << src.size() << std::endl; std::cout << "crypto json size: " << crypto_json_str.size() << std::endl; /* дешифруем crypto json */ std::string str = crypto_json::to_string(crypto_json_str, key, iv, type, true); /* дешифруем crypto json в класс json библиотеки nlohmann/json.hpp */ nlohmann::json j = crypto_json::to_json(crypto_json_str, key, iv, type, true); std::cout << "to json:" << std::endl << j << std::endl; /* зашифруем данные класса библиотеки nlohmann/json.hpp */ std::string crypto_json_str2 = crypto_json::to_crypto_json(j, key, iv, type, true);
JSON эт неплохо. Но зачем его сжимать не пойму. Неужели такой громадный?
А шифровать? — от кого?
Велосипед
Когда у меня было распространяемое ПО,
то я критически важные сборки через WEB на клиентские места загружал.
То есть на клиентском месте не было важных сборок, а ПО работало.
Чудеса.
А на сервере моем было видно кто и что загружает, на какие IP.
Если IP не зарегистрированы, то сразу «футбол».
И maintance значительно упрощалось.
Все сборки лежали в одном месте на сервере, были «up to date».
ТО есть пользователь не нуждался в дополнительных update-ах, они по определению были всегда свежими.
нет конкретного назавания сборок.
Для каждого пользователя загружается конкретная конфигурация, которая состоит из сборок, файлов конфигурации и др вспомогательных файлов. Все загружается в сжатом виде с ключом.
Все сборки сразу грузятся в память, на диске не сохраняются.
В дебагере, конечно, можно посмотреть что «что-то» загружается, а что конкретно летит определить сложно.
И пользователь не в курсе, что сборки грузятся извне.
Он думает, что все файлы есть на диске.
Специалист, конечно, раскопает. Но обычный, или даже продвинутый пользователь не справится.
Еще есть способы борьбы с дебагерами. Путем замера времени исполнения определенных частей кода. Замеры делаются обычно в нескольких разных потоках одновременно, не в основном потоке выполнения.
Если время исполнения кода превышено, то значит дебажат ...
Но у меня этого нет, поэтому нюансов не знаю. Сам не пробовал.
Но идея вроде хороша на первый взгляд.