Как зашифровать одну процедуру 1С и привязать её к ИНН покупателя

11.11.26

Администрирование - Информационная безопасность

Вы вложили в одну процедуру всю ценность - формулу, коэффициенты, алгоритм, - продали обработку одному клиенту, а её тут же раздают дальше. Проверку ИНН прямо в коде вырезают за минуту: тело процедуры лежит рядом открытым текстом. Разбираю, как вместо этого зашифровать тело процедуры ключом из ИНН покупателя и получить готовый блок КодПодИНН для вставки в свою обработку: на чужом ИНН видно шифроблок, а не ваш алгоритм, и процедура не выполняется. Весь механизм на чистом BSL - потоковый шифр на штатном SHA-256 с нонсом, раздельные ключи и тег на HMAC, без СЛК и внешних компонент. И честно про потолок: почему это конфиденциальность логики, а не жёсткая привязка. В комплекте бесплатная демо-обработка.

Знакомая история: вы написали процедуру, в которой вся ценность, - свою формулу, коэффициенты, алгоритм, - вложили её в обработку и продали одному клиенту. А через месяц встречаете эту обработку у трёх других. Файл .epf копируется мышкой, и остановить это договором трудно. Хочется, чтобы та самая процедура работала только у того, кто её купил.

Первое, что приходит в голову, - проверить в коде ИНН организации и выйти, если он чужой. Я покажу, почему это вообще не защита, как вместо неё зашифровать тело одной процедуры и привязать его к ИНН покупателя, и, честно, где у такой защиты потолок. Обработка на входе берёт тело процедуры, а на выходе отдаёт готовый кусок кода для вставки в вашу обработку. Весь механизм - на чистом встроенном языке, без СЛК, без внешних компонент и без покупки ключей.

 

Почему проверка ИНН в коде не защищает

Самый частый совет на форумах звучит так:

Если Организация.ИНН <> "600900529130" Тогда
    Возврат; // чужая база - выходим
КонецЕсли;
// ... дальше полезная логика ...

Полезная логика лежит рядом, открытым текстом. Тот, кто захочет снять привязку, открывает модуль, находит это Если и удаляет три строки. Код под ним никуда не делся, он просто начинает выполняться у всех. Пароль на модуль тут помогает слабо: его снимают теми же общедоступными средствами, которыми снимают пароль с любой внешней обработки.

Проверка ИНН - это замок, повешенный на дверь рядом с открытым окном. Главную ценность, тело вашей процедуры с логикой и коэффициентами, она не прячет вовсе: его видно в модуле сразу.

 

Что меняет шифрование тела процедуры

Тело процедуры - сам алгоритм, коэффициенты, любой текст кода - храним в обработке в зашифрованном виде. Ключ не лежит в файле: он выводится из ИНН покупателя и секрета разработчика. На верном ИНН ключ собирается правильно, тело расшифровывается и выполняется. На чужом ИНН ключ другой, и расшифровки нет - выполнять нечего.

Честно сразу о границе, чтобы дальше читать с правильными ожиданиями. Шифрование решает одну задачу: конфиденциальность. Конкурент, которому попал файл, видит шифроблок; тело процедуры закрыто, и просто так его не прочитать. Это ровно то, чего проверка ИНН не даёт никогда. А вот жёсткой привязки к одному покупателю шифрование само по себе не обеспечивает, и ниже я покажу, почему. Это не DRM и не замок на тираж, это способ не отдавать свою процедуру в открытом виде.

 

Схема: разработчик шифрует тело процедуры под ИНН покупателя, на выходе готовый блок КодПодИНН; покупатель вставляет его, процедура расшифровывает себя под ИНН своей базы

 

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

 

Чем шифровать на встроенном языке

Штатного симметричного шифра вроде AES в платформе нет. Зато в любой современной версии есть ХешированиеДанных с SHA-256, и этого достаточно, чтобы собрать потоковый шифр в режиме счётчика. Схема собирается из трёх понятных кусков.

Ключ из ИНН. Мастер-ключ = SHA256(ИНН + "|" + секрет), 32 байта. Из него я вывожу два отдельных ключа: один для шифрования, другой для тега подлинности. Разделять их - дешёвая гигиена: один и тот же ключ не должен работать в двух ролях.

Функция КлючИзИНН(ИНН, Секрет)
    Хэш = Новый ХешированиеДанных(ХешФункция.SHA256);
    Хэш.Добавить(ПолучитьДвоичныеДанныеИзСтроки(СокрЛП(ИНН) + "|" + Секрет, "UTF-8"));
    Возврат Хэш.ХешСумма;
КонецФункции

// Производный ключ = HMAC-SHA256( мастер-ключ, метка ).
Функция Подключ(МастерКлючДД, Метка)
    Возврат HMAC_SHA256(МастерКлючДД, ПолучитьДвоичныеДанныеИзСтроки(Метка, "UTF-8"));
КонецФункции

Гамма с нонсом. Гамму (псевдослучайный поток для XOR) я вырабатываю по блокам: блок i = HMAC-SHA256(ключ шифра, версия + нонс + счётчик i). Нонс - это 32 случайных символа, свои на каждую упаковку. Без него возникает классическая дыра потокового шифра: если упаковать тем же ключом два текста, XOR двух шифроблоков равен XOR открытых текстов, и, зная один, восстанавливаешь второй без всякого ключа. Для тиражного решения это реальный сценарий - вы переупаковываете обновление процедуры тому же покупателю. Нонс эту дыру закрывает: тот же ключ, другой нонс, другая гамма.

Счётчик блока я кладу четырьмя байтами, а не через Строка(ИндексБлока). Строковое представление числа зависит от региональных настроек: 1000 в одной базе даёт "1000", в другой - "1 000" с неразрывным пробелом. Если упаковать в одной базе, а распаковать в другой, гамма разойдётся после блока 1000, и MAC этого не заметит - он проверяет нонс и шифртекст, а не способ построения счётчика. Четыре байта big-endian от локали не зависят.

Функция Гаммировать(ВходБуф, КлючШифраДД, НонсДД)
    РазмерБлока = 32;
    Длина = ВходБуф.Размер;
    ВыходБуф = Новый БуферДвоичныхДанных(Длина);
    ОснованиеДД = СоединитьДД(ВерсияДД(), НонсДД);
    ГаммаБуф = Неопределено;
    Для Сч = 0 По Длина - 1 Цикл
        ИндексБлока = Цел(Сч / РазмерБлока);
        ПозицияВБлоке = Сч - ИндексБлока * РазмерБлока;
        Если ПозицияВБлоке = 0 Тогда
            Сообщение = СоединитьДД(ОснованиеДД, СчётчикДД(ИндексБлока));
            ГаммаБуф = ПолучитьБуферДвоичныхДанныхИзДвоичныхДанных(HMAC_SHA256(КлючШифраДД, Сообщение));
        КонецЕсли;
        ВыходБуф.Установить(Сч, ПобитовоеИсключительноеИли(ВходБуф.Получить(Сч), ГаммаБуф.Получить(ПозицияВБлоке)));
    КонецЦикла;
    Возврат ВыходБуф;
КонецФункции

Функция СчётчикДД(Индекс)
    Буф = Новый БуферДвоичныхДанных(4);
    Буф.Установить(0, Цел(Индекс / 16777216) % 256);
    Буф.Установить(1, Цел(Индекс / 65536) % 256);
    Буф.Установить(2, Цел(Индекс / 256) % 256);
    Буф.Установить(3, Индекс % 256);
    Возврат ПолучитьДвоичныеДанныеИзБуфераДвоичныхДанных(Буф);
КонецФункции

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

Тег подлинности. Чтобы отличить "расшифровалось правильно" от "получился мусор под чужим ИНН", к пакету прикладывается тег: HMAC-SHA256(ключ тега, версия + нонс + шифртекст), проверяется до расшифровки (encrypt-then-MAC). Нонс всегда ровно 32 символа, и это важно: распаковщик сначала проверяет длину и hex-формат нонса, поэтому границы полей в сообщении HMAC однозначны, и никто не "перельёт" байт из нонса в шифртекст, оставив тег прежним. HMAC здесь не для красоты: голый SHA256(ключ + текст) уязвим к удлинению сообщения, HMAC по RFC 2104 этого класса проблем лишён. Полная реализация HMAC на ХешированиеДанных - в демо-обработке; копируется вместе со вспомогательной функцией склейки двоичных данных.

Упаковка и распаковка

Функция Зашифровать(Текст, ИНН, Секрет) Экспорт
    МастерКлюч = КлючИзИНН(ИНН, Секрет);
    КлючШифра = Подключ(МастерКлюч, "enc");
    КлючТега = Подключ(МастерКлюч, "mac");

    Нонс = НовыйНонс();
    НонсДД = ПолучитьДвоичныеДанныеИзСтроки(Нонс, "UTF-8");
    ОткрытыйБуф = ПолучитьБуферДвоичныхДанныхИзДвоичныхДанных(ПолучитьДвоичныеДанныеИзСтроки(Текст, "UTF-8"));
    ШифрБуф = Гаммировать(ОткрытыйБуф, КлючШифра, НонсДД);
    ШифрДД = ПолучитьДвоичныеДанныеИзБуфераДвоичныхДанных(ШифрБуф);

    Результат = Новый Структура;
    Результат.Вставить("Нонс", Нонс);
    Результат.Вставить("Шифр", Base64Строка(ШифрДД));
    Результат.Вставить("Тег", Base64Строка(ВычислитьТег(КлючТега, НонсДД, ШифрДД)));
    Возврат Результат;
КонецФункции

Функция Расшифровать(Шифр64, Тег, Нонс, ИНН, Секрет) Экспорт
    Результат = Новый Структура("Успех, Текст, Сообщение", Ложь, "", "");
    Попытка
        ШифрДД = Base64Значение(Шифр64);
        ТегОжидаемыйДД = Base64Значение(СокрЛП(Тег));
    Исключение
        Результат.Сообщение = "Шифроблок или тег не распознаны как Base64.";
        Возврат Результат;
    КонецПопытки;

    НонсЧист = СокрЛП(Нонс);
    Если НЕ НонсКорректен(НонсЧист) Тогда // ровно 32 hex-символа
        Результат.Сообщение = "Нонс повреждён: нужно ровно 32 hex-символа.";
        Возврат Результат;
    КонецЕсли;

    МастерКлюч = КлючИзИНН(ИНН, Секрет);
    КлючТега = Подключ(МастерКлюч, "mac");
    НонсДД = ПолучитьДвоичныеДанныеИзСтроки(НонсЧист, "UTF-8");

    Если Base64Строка(ВычислитьТег(КлючТега, НонсДД, ШифрДД)) <> Base64Строка(ТегОжидаемыйДД) Тогда
        Результат.Сообщение = "ИНН не совпал: доступ закрыт.";
        Возврат Результат;
    КонецЕсли;

    КлючШифра = Подключ(МастерКлюч, "enc");
    ОткрытыйБуф = Гаммировать(ПолучитьБуферДвоичныхДанныхИзДвоичныхДанных(ШифрДД), КлючШифра, НонсДД);
    Результат.Успех = Истина;
    Результат.Текст = ПолучитьСтрокуИзДвоичныхДанных(ПолучитьДвоичныеДанныеИзБуфераДвоичныхДанных(ОткрытыйБуф), "UTF-8");
    Возврат Результат;
КонецФункции

Пакет - это три поля: нонс, шифр, тег. Они передаются вместе, шифроблок без своего нонса не расшифровать. Проверка идёт через тег, минуя попытку привести расшифрованные байты к строке: на чужом ИНН мусорные байты могли бы и не быть валидным UTF-8, тег закрывает вопрос раньше.

 

Готовый блок для вставки: функция КодПодИНН

Три поля руками переносить неудобно, поэтому обработка собирает их в готовую функцию. Вводите тело процедуры (оно работает с переменными Вход и Результат), ИНН покупателя и секрет, жмёте "Собрать блок" - и получаете кусок кода, который копируется в модуль вашей обработки целиком:

Функция КодПодИНН()
    Нонс   = "bb44b650d3244f529e1ec63ad62383a5";
    Шифр64 = "pagVRLscOUDULgqcb7qVTvdzWEhO4V5mX/k0cLKpZH9Bjp+cpSjkL/mwqWtViV8PPw==";
    Тег64  = "j5YD1t7pZnPaMzJonwdZs6EHm75NCIGhL8hS7qRhkMg=";
    Секрет = "ваш-секрет";  // держите секрет у себя
    Пакет = Расшифровать(Шифр64, Тег64, Нонс, ИННПервойОрганизации(), Секрет);
    Если НЕ Пакет.Успех Тогда
        ВызватьИсключение "Экземпляр выдан другой организации.";
    КонецЕсли;
    Возврат Пакет.Текст;
КонецФункции

Функции расшифровки (ключ из ИНН, HMAC, гаммирование) копируются из демо-обработки один раз - код открыт. После этого ваша процедура у покупателя становится тонкой: в ней нет ни алгоритма, ни коэффициентов, только вызов.

Функция Наценка(Вход) Экспорт
    Результат = 0;
    Выполнить(КодПодИНН()); // тело расшифровывается под ИНН базы и выполняется здесь
    Возврат Результат;
КонецФункции

КодПодИНН читает ИНН текущей базы, расшифровывает тело и отдаёт его на Выполнить. Тело работает с теми же Вход и Результат, что вы задали при упаковке. Совпал ИНН - процедура считает как считала, не совпал - Расшифровать не проходит, и обработка честно отказывает. В модуле при этом не видно ни формулы, ни чисел: только шифроблок.

 

Где взять ИНН в базе покупателя

ИНН можно подставить из базы, чтобы не вводить руками. Но честная оговорка: ВЫБРАТЬ ПЕРВЫЕ 1 без порядка возвращает произвольную подходящую организацию, не обязательно основную. В базе с несколькими юрлицами это не "основная организация", и в прикладном коде организацию надо выбирать явно. Для демо кнопка так и называется - "Взять ИНН первой организации", и форма предупреждает, что результат стоит проверить глазами.

Функция ИННПервойОрганизации() Экспорт
    Попытка
        Если Метаданные.Справочники.Найти("Организации") = Неопределено Тогда
            Возврат "";
        КонецЕсли;
        Запрос = Новый Запрос;
        Запрос.Текст =
            "ВЫБРАТЬ ПЕРВЫЕ 1 ИНН КАК ИНН
            |ИЗ Справочник.Организации
            |ГДЕ НЕ ПометкаУдаления И ИНН <> """"";
        Выборка = Запрос.Выполнить().Выбрать();
        Если Выборка.Следующий() Тогда
            Возврат СокрЛП(Выборка.ИНН);
        КонецЕсли;
    Исключение
        Возврат "";
    КонецПопытки;
    Возврат "";
КонецФункции

 

Что показал прогон на стенде

Собрал демо-обработку и прогнал на платформе 8.3.27. В тело положил простую наценку Результат = Число(Вход) * 1.37;, ИНН покупателя и секрет, собрал блок КодПодИНН. Потом проверил его выполнение - не только счастливый путь:

  • под верным ИНН тело выполняется: вход 1000 даёт Результат 1370, round-trip тела точный на длинах 0, 31, 32, 33, 64 байта и на многобайтном UTF-8 (кириллица, символы валют);
  • под чужим ИНН тег не сходится, тело не отдаётся и не выполняется, обработка бросает исключение;
  • две упаковки одного тела одним ключом дают разные нонс и шифроблок - дыра повторной гаммы закрыта;
  • подмена нонса или тега, пустой нонс - доступ закрыт.

В собранном блоке нонс ровно 32 символа, шифроблок и тег - одной строкой (переносы Base64Строка снимаются при сборке, иначе литерал в коде порвётся). Обработка не пишет в базу, не лезет в таблицы напрямую и работает только штатными методами платформы.

 

Честно про потолок: чего это не делает

А теперь то, из-за чего я переписал эту статью после внешнего ревью. Привязку к одному покупателю шифрование не гарантирует, и обещать обратное было бы враньём. Секрет разработчика по определению едет внутри клиентского модуля боевой обработки, и из этого следуют два обхода, которым даже не нужно доставать секрет.

  • Подставить чужой ИНН. У кого есть доступ к редактированию модуля, тот подставляет в вызов расшифровки ИНН законного покупателя, с чьей копии разошёлся файл. Код сам знает секрет и сам всё расшифрует.
  • Снять открытый текст после расшифровки. У законного покупателя КодПодИНН штатно расшифровывает тело в памяти - его оттуда и забирают, не трогая ни секрет, ни схему.

Поэтому никакого "взломать дороже, чем купить" я не обещаю: доказанного порога стоимости тут нет. Пароль на модуль, кстати, защищает и обычную проверку ИНН, так что сам по себе он преимущества шифрования не создаёт.

Что шифрование реально даёт, честно: тело процедуры не видно в открытом виде, и случайное распространение файла не раскрывает алгоритм и коэффициенты. Планка снятия привязки поднимается с "удалить три строки" до "возьми скопированный файл, узнай исходный ИНН покупателя и поправь вызов расшифровки". Рабочая база покупателя для этого не нужна, хватает файла. Насколько это кого-то остановит на практике - вопрос открытый, цифр у меня нет. Для защиты логики от прямого копирования это работает, для настоящей лицензии - нет.

Следующий уровень - подпись лицензии ключом, которого у покупателя в принципе нет, это уже асимметричная криптография. Как её поднять на чистом встроенном языке, без COM и .NET, я разбирал отдельно в статье RSA на встроенном языке 1С.

 

Демо-обработка

К статье приложена бесплатная демо-обработка: вводите тело процедуры, ИНН покупателя и секрет, жмёте "Собрать блок" - получаете готовую КодПодИНН для вставки, и тут же, ниже на форме, проверяете её выполнение под верным и под чужим ИНН. Наверху формы - описание, что она делает, а кнопка "Справка (FAQ)" открывает ответы на частые вопросы. Ядро внутри - ровно то, что выше по тексту, плюс полная реализация HMAC. Скачать можно на странице демо-обработки "Привязка процедуры к ИНН".

Другие наши инструменты:

  • Анализ кода внешних обработок - разбирает чужую или свою .epf и показывает, что внутри: опасные конструкции, прямой доступ к таблицам, тяжёлые места. Соседний угол к этой статье: там мы прячем процедуру, здесь читаем чужую.
  • Помощник перехода на 1С 8.5 - тот же разбор кода, только вопрос другой: что перестанет работать после смены платформы.
  • Трансформатор SQL в 1С - переводит запрос из профайлера обратно в имена справочников и регистров, когда видно, что база тормозит, а чей это запрос непонятно.
  • Чек-ап СУБД под 1С - диагностика сервера, когда код чистый, а тормозит всё равно.

Открытый вопрос, на который у меня нет однозначного ответа: стоит ли вообще городить клиентскую защиту для одной процедуры в интерпретируемом языке, где секрет всё равно едет к покупателю? Или честнее отдавать дёшево и держать привязку в договоре? Где у вас проходит граница между "защитил" и "потратил на защиту больше, чем она стоит"?

Вступайте в нашу телеграмм-группу Инфостарт

зашифровать процедуру привязка к ИНН защита кода обработки шифрование SHA-256 HMAC BSL внешняя обработка КодПодИНН

Вы можете заказать платную адаптацию этой статьи под ваши задачи на «Бирже заказов».

  • 0% комиссии — оплата напрямую исполнителю;
  • Исполнители любого масштаба — от отдельных специалистов до команд под проект;
  • Прямой обмен контактами между заказчиком и исполнителем;
  • Безопасная сделка — при необходимости;
  • Рейтинги, кейсы и прозрачная система откликов.

См. также

Информационная безопасность Чистка данных Системный администратор Разработчик Руководитель проекта 1С 8.3 1С:Бухгалтерия 3.0 Платные (руб)

Обезличивает копию рабочей базы 1С перед передачей наружу и возвращает настоящие данные обратно, когда база вернулась. Это обратимая псевдонимизация: соответствия «исходное - псевдоним» пишутся в отдельный зашифрованный датасет, который остаётся у владельца. Работает на любой конфигурации - обходит метаданные и находит персональные данные сам, без списка реквизитов под конкретную базу. Суммы, количества, даты и номера документов не трогает никогда, оборотно-сальдовая до и после совпадает до копейки. Проверено на трёх конфигурациях: 106 031 объект, 215 642 замены, ноль ошибок, возврат 100 процентов.

42700 руб.

18.08.2026    1532    3    0    

3

Информационная безопасность Инструменты администратора БД Инструментарий разработчика Учет документов Системный администратор Разработчик Аналитик Бухгалтер Пользователь Руководитель проекта 1С 8.3 1С 8.5 Розничная и сетевая торговля (FMCG) Платные (руб)

Контроль ввода данных в 1С: проверка заполнения реквизитов, обязательные поля, контроль перед записью и проведением, запрет проведения документа. Позволяет настраивать любые проверки данных в 1С 8.3/8.5 от обязательных полей до сложных условий – без открытия конфигуратора и написания кода. Готовое расширение, которое подключается и работает сразу.

6000 руб.

15.04.2026    4186    12    0    

25

Информационная безопасность Нейросети Разработчик 1С 8.3 Бесплатно (free)

Скрипт, который написал Claude Code и каждый час запускал планировщик, ночью пометил на удаление тысячи документов перемещений в продуктивной базе 1С на 5 ТБ. Остатки уехали на миллиардные суммы, база стояла до обеда, около 500 заказов с маркетплейсов и сайта ушли в отмены. Как это произошло, где была ошибка в определении дублей и что я сделал, чтобы это не повторилось: агентам только чтение, алерты в Telegram на массовую запись, ревизия планировщиков.

06.10.2026    6365    nedomolkov.ivan    164    

48

Информационная безопасность Поиск данных ServiceDesk, HelpDesk Журналы и реестры данных 1С 8.3 Россия Бухгалтерский учет Бюджетный учет Налоговый учет Управленческий учет Платные (руб)

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

180000 руб.

05.09.2025    5948    2    1    

4

Информационная безопасность Пароли 1С:Предприятие 8 Бесплатно (free)

Все еще храните пароли в базе? Тогда мы идем к вам! Безопасное и надежное хранение секретов. JWT авторизация. Удобный интерфейс. Демо конфигурация. Бесплатно.

30.05.2024    17618    kamisov    20    

66

Информационная безопасность Разработчик 1С:Предприятие 8 Бесплатно (free)

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

27.02.2024    27281    AlexeyPROSTO_1C    10    

46

Информационная безопасность Системный администратор 1С:Предприятие 8 1C:Бухгалтерия Россия Абонемент ($m)

Продукты на основе решений 1С уверенной поступью захватывают рынок учётных систем в стране. Широкое распространение программ всегда порождает большой интерес к ним со стороны злоумышленников, а пользователь 1С это одна из дверей в защищённый информационный контур предприятия. Обработка позволяет быстро и комплексно оценить настройки безопасности конкретной базы и возможности пользователя этой базы на сервере. Также можно оценить некоторые аспекты сетевой безопасности предприятия со стороны сервера 1С.

5 стартмани

24.04.2023    10012    31    soulner    8    

35
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. Flover 67 11.11.26 11:33 Сейчас в теме
Я когда то давным давно еще лет дцать назад делал вебсервис, который возвращал посчитанные значения, в клиенте никаких алгоритмов не хранилось. Узкое место правда было - если в/с падал, клиент "курил".
Еще есть вариант - алгоритмы хранить в файле в виде двоичных данных(считай компонента)
2. DmitryKSL 187 11.11.26 11:43 Сейчас в теме
Тут проблема в том, что изначально кто захочет скопировать, может взять код только у легального владельца. Т.е. он скорее всего знает ИНН "нулевого пациента" и вся дальнейшая защита не имеет смысла. А так идея интересная.
3. vik070777 278 11.11.26 12:29 Сейчас в теме
Продажа одной обработки одному клиенту, где основная угроза — «клиент отдал файл коллеге/знакомому», а не целенаправленный реверс. Случайный слив алгоритм не раскрывает.
Это интересно как «замок от любопытных», а не от конкурента.

В принципе прикольно)
Для отправки сообщения требуется регистрация/авторизация