Защита тиражной обработки 1С от копирования: три уровня и где у каждого потолок
Иван Недомолков · Жарияланды:
Вы написали внешнюю обработку, вложили в неё свой алгоритм и коэффициенты, продали одному клиенту. Через месяц видите её у трёх других. Файл .epf копируется мышкой, и остановить это договором трудно: к моменту, когда вы узнаете о распространении, копии уже разошлись.
Защиту от этого обычно выбирают по первому совету с форума и останавливаются на самом слабом варианте. Чтобы выбирать осознанно, разложим защиту на три уровня по тому, насколько трудно её снять. У каждого свой потолок, и честный ответ про потолок важнее красивого обещания: ни один из уровней на чистом встроенном языке не даёт настоящего DRM, и знать, где именно он протекает, нужно до того, как вы на него понадеетесь.
Три уровня защиты одним взглядом
| Уровень | Что делает | От чего защищает | Где протекает |
|---|---|---|---|
| 0. Проверка ИНН в коде | Если ИНН <> "…" Тогда Возврат | ни от чего | логика рядом открытым текстом, снимается за минуту |
| 1. Шифрование логики под ИНН | тело процедуры зашифровано, ключ из ИНН покупателя | конфиденциальность: конкурент видит шифр, а не алгоритм | секрет едет в клиентском модуле, привязку можно обойти |
| 2. Асимметричная лицензия | подпись ключом, которого у покупателя нет | ближе к настоящей лицензии | сложнее в реализации, нужна отдельная схема |
Дальше по каждому уровню: как он выглядит в коде, что закрывает на деле и когда его брать.
Уровень 0: проверка ИНН - это не защита
Самый частый совет звучит так: сравни в коде ИНН организации и выйди, если он чужой.
Если Организация.ИНН <> "600900529130" Тогда
Возврат; // чужая база - выходим
КонецЕсли;
// ... дальше полезная логика ...
Проблема не в том, что проверку легко найти. Проблема в том, что защищать тут нечего: ваша ценная логика лежит в том же модуле открытым текстом, прямо под этим Если. Тот, кто захочет снять привязку, открывает модуль, удаляет три строки условия - и код под ними начинает выполняться у всех. Алгоритм и коэффициенты он при этом видел с самого начала, они никуда не были спрятаны.
Пароль на модуль тут почти не помогает: его снимают теми же общедоступными средствами, которыми снимают пароль с любой внешней обработки. Проверка ИНН - это замок на двери рядом с открытым окном. Как единственная мера она не стоит потраченного на неё времени.
Уровень 1: шифрование тела процедуры под ИНН
Рабочая середина выглядит иначе: ценную часть не охраняют проверкой, а держат в зашифрованном виде. Тело одной процедуры - алгоритм, коэффициенты, любой код - хранится в обработке шифроблоком. Ключ не лежит в файле: он выводится из ИНН покупателя и вашего секрета. На верном ИНН ключ собирается правильно, тело расшифровывается и выполняется; на чужом ИНН ключ другой, и расшифровки нет - выполнять нечего.
Шифровать можно средствами самой платформы, без СЛК и внешних компонент. Штатного AES в 1С нет, но есть ХешированиеДанных с SHA-256, и этого достаточно для потокового шифра в режиме счётчика:
- ключ из ИНН: мастер-ключ =
SHA256(ИНН + "|" + секрет), из него два отдельных подключа (один шифрует, другой считает тег подлинности - разные роли, разные ключи); - гамма с нонсом: псевдослучайный поток для XOR, по блокам
HMAC-SHA256(ключ, версия + нонс + счётчик); нонс свой на каждую упаковку, иначе две упаковки одним ключом раскрывают друг друга; - тег подлинности:
HMAC-SHA256, проверяется до расшифровки (encrypt-then-MAC), чтобы отличить верный ИНН от мусора под чужим, не пытаясь привести мусорные байты к строке.
Главное для вас как для автора - не вставлять три поля руками. Инструмент собирает из них готовую функцию, которую вы копируете в модуль своей обработки целиком:
Функция КодПодИНН()
Нонс = "57a8d6eea48a46ee8e9017d9acb1e08e";
Шифр64 = "tMnVPmcP60vio/W8fA4JsvkVEdn/wp2bYQPLruvxPfsY2F+9Fzwtq/QzEoDuMEdQ9g==";
Тег64 = "WWWEe7GcLcvwrOgUFOO6yYKFdKWD6L04n0hivbvok/c=";
Секрет = "ваш-секрет"; // держите секрет у себя
Пакет = Расшифровать(Шифр64, Тег64, Нонс, ИННПервойОрганизации(), Секрет);
Если НЕ Пакет.Успех Тогда
ВызватьИсключение "Экземпляр выдан другой организации.";
КонецЕсли;
Возврат Пакет.Текст;
КонецФункции
Функции расшифровки (ключ из ИНН, HMAC, гаммирование) переносите из демо-обработки один раз - код открыт. После этого ваша процедура у покупателя становится тонкой: в ней нет ни алгоритма, ни чисел, только вызов.
Функция Наценка(Вход) Экспорт
Результат = 0;
Выполнить(КодПодИНН()); // тело расшифровывается под ИНН базы и выполняется здесь
Возврат Результат;
КонецФункции
Совпал ИНН базы - процедура считает как считала; не совпал - расшифровка не проходит, и обработка честно отказывает. В модуле при этом не видно ни формулы, ни коэффициентов: только шифроблок.
Что этот уровень реально даёт, а что нет
Честно о границе, потому что именно здесь чаще всего обещают лишнее. Шифрование закрывает конфиденциальность логики: конкурент, которому попал файл, видит шифр, а не ваш алгоритм. Проверка ИНН этого не давала никогда.
Но жёсткой привязки к одному покупателю оно не даёт. Секрет разработчика по определению едет внутри клиентского модуля, и отсюда два обхода, которым даже не нужно его доставать:
- подставить чужой ИНН: у кого есть доступ к редактированию модуля, тот подставляет в вызов расшифровки ИНН законного покупателя - код сам знает секрет и сам всё расшифрует;
- снять открытый текст после расшифровки: у законного покупателя тело штатно расшифровывается в памяти, оттуда его и забирают, не трогая ни секрет, ни схему.
Поэтому обещания «взломать дороже, чем купить» тут нет: планка снятия привязки поднимается всего лишь с «удалить три строки» до «возьми копию файла, узнай исходный ИНН покупателя и поправь вызов расшифровки». Для защиты логики от прямого копирования это работает, для настоящей лицензии - нет.
Готовая демо-обработка с этим механизмом (собрать блок, проверить под верным и под чужим ИНН) лежит у нас на Инфостарте, а полный разбор реализации со всем кодом HMAC и потокового шифра - в статье-методе там же. Сайтовая версия собрана как выбор уровня защиты, статья - как сам механизм по шагам.
Уровень 2: асимметричная лицензия
Чтобы привязку нельзя было обойти подменой ИНН, нужен ключ, которого у покупателя в принципе нет. Это уже асимметричная криптография: вы подписываете лицензию приватным ключом, обработка проверяет подпись публичным, а подделать подпись без приватного ключа нельзя. Секрет при этом не едет к покупателю, и оба обхода уровня 1 закрываются.
Цена - сложность: нужна длинная арифметика по модулю на встроенном языке, без COM и .NET (чтобы работало и на Linux-сервере, и в тонком клиенте). Как поднять RSA нативно на BSL, мы разбирали отдельно - RSA-шифрование в 1С без внешних компонент. Это следующий уровень для тех, кому мало конфиденциальности и нужна именно лицензия.
Как выбрать уровень под задачу
- Не берите уровень 0 как единственную меру - он не защищает ничего, а только создаёт ощущение защиты.
- Уровень 1 берут, когда задача - не отдавать свою логику в открытом виде: чтобы конкурент с чужой копией файла не прочитал алгоритм и коэффициенты. Это закрывает случайное распространение и прямое копирование логики. Реализуется за часы, на одних платформенных методах.
- Уровень 2 берут, когда нужна настоящая лицензия и защита от целенаправленного обхода, и вы готовы платить за это сложностью.
Трезвый итог: в интерпретируемом языке, где код приезжает к покупателю, идеальной защиты нет. Вопрос не «как сделать невзламываемо», а «какой уровень окупает потраченное на него время при вашей цене и вашем тираже». Чаще всего честный ответ - уровень 1 плюс нормальный договор, а не бесконечная гонка за DRM.
Если вам нужно встроить такую защиту в конкретную обработку или собрать продукт, который вы отдаёте клиентам, мы делаем это под ключ - от схемы до готового кода.