Блог им. elektroyar

Зашифрованный и сжатый JSON с комментариями в качестве файла конфигурации

В процессе разработки ПО для трейдинга столкнулся с тем, что программа должна иметь целую кучу файлов конфигурации, содержание которых хотелось бы скрыть от пользователя. Это могут быть настройки стратегий, параметры авторизации на сервере, текст для разных языков интерфейса и т.д.

Для файлов конфигурации я уже давно использую файлы с JSON. Очень удобная вещь. Осталось лишь добавить поддержку комментариев и зашифровать текст при помощи алгоритма AES. А для большей красоты еще и сжать текст перед шифровкой алгоритмом brotli.

Сказано — сделано. Встречайте — crypto-jsonпроект на гитхабе. Репозиторий содержит готовый редактор JSON с комментариями, который может также сохранить текст в зашифрованном виде. Настройки сжатия и шифрования можно задать перед сохранением файла и во время открытия. Также редактор позволяет сделать проверку JSON и может подсвечивать проблемные места.

Зашифрованный и сжатый JSON с комментариями в качестве файла конфигурации
Зашифрованный и сжатый JSON с комментариями в качестве файла конфигурации


Работа с зашифрованными JSON файлами в C++


Для использования зашифрованных файлов в программе библиотека содержит простые функции. Покажу пример кода, который раскрывает почти все возможности библиотеки:

#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);
★7
31 комментарий

JSON эт неплохо. Но зачем его сжимать не пойму. Неужели такой громадный?
А шифровать? — от кого?

avatar
3Qu, я делаю ПО для трейдеров, чтобы стричь с них проценты от прибыли. Будет не комильфо, если они будут открывать файлы и видеть там настройки стратегий, подключений к серверам и т.д. Сжатие добавил перфекционизма ради, ну к тому же дешифрованные данные будут не понятны, так как их надо еще разархивировать. +1 к усложнению взлома. 
avatar
elektroyar, вы сильно переоцениваете интеллектуальные способности «трейдеров», покупающих стратегии…
avatar
elektroyar, а разве на сами трейдеры изначально будут вводить все эти данные через интерфейс программы?
Игорь Шумилов, некоторые данные вводить не будут же, например если у меня есть свой сервер, который ведет учет прибыли или раздает сигналы. Можно в файле хранить токен к примеру, который может быт разный у разных пользователей. Главное в самой программе ключ от файла хранить тоже в зашифрованном виде, и код всячески запутать, чтобы реверс инженеру жизнь сладкой не показалась. Но это уже другая тема. 
avatar
elektroyar, можно задуматься о том, насколько законна передача такой информации на Ваш сервер и достаточно ясно ли понимают Ваши клиенты, что Вы храните и раскладываете у себя на машине все их позиции и сделки.
avatar
От она удача!!!
Zip с паролем ничем не хуже. И не надо тянуть лишние зависимости.
Велосипед
avatar
Дедал, а есть быстрый способ загрузить зип в программе на С++ без сторонних зависимостей?
avatar
Плюс за старания :), но не совсем понятна практическая сторона вопроса. Если вы не правите конфиг файлы руками, то сохраняйте все в бинарный формат. Сделали свою структуру данных и сохранили как байткод, никто и не разберется что там и где :)
avatar
CloseToAlgoTrading, своя структура это неплохо, но для реверс-инженера это будет не такая сложная задачка
avatar
elektroyar, ну вы ее тоже можите кодировать :). Но я ничего против вашего способа не имею. 
avatar
 А сами ключи как хранятся? ;)
Игорь Шумилов, ну это уже другая история) Есть на гитхабе библиотеки обфускаторы для С++. Они усложнят взлом программы. Есть еще специальное ПО, которое сделает из кода такую запутанную лапшу, что ее человеку нереально будет понять.  
avatar
elektroyar, т.е. захардкожены? А значит берётся дизассемблер и находится тот кусок памяти, откуда читается ключ :)
Само использование С++ — достаточная защита.
avatar
ch5oh, у меня знакомый программист к игре Готика писал СДК, он реверс-инженер. Отсутствие исходников ему не помешало, как видишь. Я ему для примера кидал одну свою программу, которая конектится к брокеру, и спросил сможет ли он вытащить алгоритм взаимодействия с брокером. Для него это вопрос небольшого времени, если код программы не запутан. С++ для него после компиляции набор «понятного» ему ассемблера, почти как предоставить исходники, просто погеморойнее.
avatar
elektroyar, ага, есть такие таланты. Хорошо, что они не торгуют. 
avatar
Все пральна. Защищаться надо.
Когда у меня было распространяемое ПО,
то я критически важные сборки через WEB на клиентские места загружал.
То есть на клиентском месте не было важных сборок, а ПО работало.
Чудеса.
А на сервере моем было видно кто и что загружает, на какие IP.
Если IP не зарегистрированы, то сразу «футбол».
И maintance значительно упрощалось.
Все сборки лежали в одном месте на сервере, были «up to date».
ТО есть пользователь не нуждался в дополнительных update-ах, они по определению были всегда свежими.
avatar
_sg_, это же видно в дебаггере, что какие-то сборки скачаны. А дальше дело техники. Ну и привязка по IP — довольно жесткое ограничение по нашим временам.
avatar
ch5oh, 
нет конкретного назавания сборок.
Для каждого пользователя загружается конкретная конфигурация, которая состоит из сборок, файлов конфигурации и др вспомогательных файлов. Все загружается  в сжатом виде с ключом.
Все сборки сразу грузятся в память, на диске не сохраняются.
В дебагере, конечно, можно посмотреть что «что-то» загружается,  а что конкретно летит определить сложно.
И пользователь не в курсе, что сборки грузятся извне.
Он думает, что все файлы есть на диске.
Специалист, конечно, раскопает. Но обычный, или даже продвинутый пользователь не справится.
avatar
ch5oh,
Еще есть способы борьбы с дебагерами. Путем замера времени исполнения определенных частей кода. Замеры делаются обычно в нескольких разных потоках одновременно, не в основном потоке выполнения.
Если время исполнения кода превышено, то значит дебажат ...
Но у меня этого нет, поэтому нюансов не знаю. Сам не пробовал.
Но идея вроде хороша на первый взгляд.
avatar

Eugene Logunov, =) мы даже выяснили выше, что есть люди, которые легко читают экзешник «с листа».

 

Кстати, вот если приложуха обязана прислать брокеру цифровую подпись, то она ведь уже не отвертится? Ведь нельзя прислать фиксированную сигнатуру, если каждый клиент обязан иметь свой уникальный приватный ключ?

 

То есть задача защиты трейдерского софта сводится к двухходовке:
1) Брокер начинает требовать от всех подключающихся предъявить свою уникальную подпись.

 

2) Производители софта выдают приватные ключи своим реальным клиентам и одновременно регистрируют эти ключи у брокеров.

 

3) Все хакеры идут лесом, потому что ни один брокер их ключ просто не примет.

 

Сработает?

avatar
Kapeks, что предложите взамен?
avatar

Eugene Logunov, для торгового софта клиентская часть полностью бесполезна без серверной. Потому что заявки всё равно должны через брокера пойти.

 

Соответственно, система асимметричных цифровых подписей должна решать задачу.

Клиент должен доказать серверу брокера, что он право имеет. А право он имеет, если заплатил денежку производителю софта. Который уведомил об этом своего брокера.

 

Причем, имхо, брокер даже не должен знать приватный ключ клиента, а только публичный. И производитель софта его не будет у себя хранить, потому что в любой момент можно перевыпустить пару...

avatar

Eugene Logunov, 

1) Речь не про отдельный сервер лицензий. Речь про то, что брокер сам делает у себя внутри своего софта проверку цифровых подписей подключений.

Заодно может проверять версию протокола / клиентской библиотеки.

 

эмулятор серверной части софта может выдавать себя за какой-то другой софт при подключении к брокеру.

Не может, потому что он не знает действующий клиентский ключ. Выдать себя за другой софт тоже самое, что выдать себя за другого клиента.

 

Клиент может договориться с брокером


Что позволено Юпитеру, с тем не поспоришь при всём желании. =)

avatar

теги блога elektroyar

....все тэги



UPDONW
Новый дизайн