Блог им. elektroyar
В процессе разработки ПО для трейдинга столкнулся с тем, что программа должна иметь целую кучу файлов конфигурации, содержание которых хотелось бы скрыть от пользователя. Это могут быть настройки стратегий, параметры авторизации на сервере, текст для разных языков интерфейса и т.д.
Для файлов конфигурации я уже давно использую файлы с 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-ах, они по определению были всегда свежими.
нет конкретного назавания сборок.
Для каждого пользователя загружается конкретная конфигурация, которая состоит из сборок, файлов конфигурации и др вспомогательных файлов. Все загружается в сжатом виде с ключом.
Все сборки сразу грузятся в память, на диске не сохраняются.
В дебагере, конечно, можно посмотреть что «что-то» загружается, а что конкретно летит определить сложно.
И пользователь не в курсе, что сборки грузятся извне.
Он думает, что все файлы есть на диске.
Специалист, конечно, раскопает. Но обычный, или даже продвинутый пользователь не справится.
Еще есть способы борьбы с дебагерами. Путем замера времени исполнения определенных частей кода. Замеры делаются обычно в нескольких разных потоках одновременно, не в основном потоке выполнения.
Если время исполнения кода превышено, то значит дебажат ...
Но у меня этого нет, поэтому нюансов не знаю. Сам не пробовал.
Но идея вроде хороша на первый взгляд.
Eugene Logunov, =) мы даже выяснили выше, что есть люди, которые легко читают экзешник «с листа».
Кстати, вот если приложуха обязана прислать брокеру цифровую подпись, то она ведь уже не отвертится? Ведь нельзя прислать фиксированную сигнатуру, если каждый клиент обязан иметь свой уникальный приватный ключ?
То есть задача защиты трейдерского софта сводится к двухходовке:
1) Брокер начинает требовать от всех подключающихся предъявить свою уникальную подпись.
2) Производители софта выдают приватные ключи своим реальным клиентам и одновременно регистрируют эти ключи у брокеров.
3) Все хакеры идут лесом, потому что ни один брокер их ключ просто не примет.
Сработает?
Eugene Logunov, для торгового софта клиентская часть полностью бесполезна без серверной. Потому что заявки всё равно должны через брокера пойти.
Соответственно, система асимметричных цифровых подписей должна решать задачу.
Клиент должен доказать серверу брокера, что он право имеет. А право он имеет, если заплатил денежку производителю софта. Который уведомил об этом своего брокера.
Причем, имхо, брокер даже не должен знать приватный ключ клиента, а только публичный. И производитель софта его не будет у себя хранить, потому что в любой момент можно перевыпустить пару...
Eugene Logunov,
1) Речь не про отдельный сервер лицензий. Речь про то, что брокер сам делает у себя внутри своего софта проверку цифровых подписей подключений.
Заодно может проверять версию протокола / клиентской библиотеки.
Не может, потому что он не знает действующий клиентский ключ. Выдать себя за другой софт тоже самое, что выдать себя за другого клиента.
Что позволено Юпитеру, с тем не поспоришь при всём желании. =)