01.09.2026
Закрытый .NET крипто-шлюз → Java в Kubernetes за 11 часов
Реверс вендорского крипто-шлюза без документации и замена его на свою Java-реализацию силами ИИ-агентов: байт-в-байт совместимая подпись, реплей боевого трафика 48/48, независимое ревью и боевое переключение с готовым откатом.
- ИИ-агенты
- реверс
- ГОСТ-крипто
- Java
- Kubernetes
Задача
В проде финтех-компании жил один компонент, который держал всю инфраструктуру на
Windows-сервере: вендорский крипто-шлюз SSLGateNet — закрытое .NET-приложение,
работающее только через Windows CAPI. Через него приложение КРЕ ходит во внешние
системы: шлюз поднимает ГОСТ-TLS и подписывает запросы ГОСТ-подписью. Пока жив этот
.exe — жив и Windows-сервер.
Задача: написать свой шлюз на Java, который слушает тот же порт, говорит тем же бинарным протоколом и делает то же самое — но на Linux. От постановки задачи до боевого переключения прошло ~11 часов активной работы; доводка продолжалась ещё несколько дней после.
Почему нельзя было «просто»
- Протокол нигде не документирован. Его пришлось восстанавливать по бинарям: декомпиляция серверного .NET-кода и разбор байткода клиентской части из вендорского приложения.
- Клиента не перепишешь. В КРЕ режима «без шлюза» физически нет, патчить вендорское приложение — тупик. Единственный путь — свой сервер, который клиент не отличит от родного.
- Крипто должно совпадать байт-в-байт. Подпись — не «похожая», а такая, которую принимает принимающая сторона. Формат оказался сложнее, чем выглядел: подпись считается над подписанными атрибутами, и совместимость упёрлась в детали DER-кодирования, которые не описаны нигде.
Реализовано 6 опкодов протокола — ровно те, которыми пользуется живой контур. Остальные осознанно отвечают ошибкой: вызывающих их систем в контуре нет.
Как работали агенты
Работа шла не одним агентом, а несколькими — с разными правами и, что важнее, разными источниками истины:
- Протокол-археолог отвечает на вопрос «как это устроено в оригинале» по декомпиляции и байткоду — и не имеет права переписать код под свой ответ.
- Крипто-инженер пишет код: подпись, ГОСТ-TLS, контейнеры ключей.
- Тестер совместимости гоняет настоящий вендорский клиент против обеих реализаций — старой и новой — и сравнивает поведение. Меряет чужим клиентом, а не нашими ожиданиями.
- Ревьюер ищет ошибки корректности и безопасности — и не имеет права чинить то, что нашёл.
Разделение — не про «разные модели умеют разное». Оно про то, чтобы ни один агент не проверял сам себя.
Система доказательств
Ключевое в этом кейсе: почти на каждом шаге был способ узнать правду, не спрашивая агента. Три внешних источника истины:
- Чужой клиент. Вендорский клиентский класс запускается как есть и натравливается на наш сервер. Тест писал не я — тест уже был написан вендором и работал годами. Это самый строгий из возможных тестов: ровно тот код, который пойдёт в прод.
- Чужой сервер. Боевой шлюз умеет проверять подписи. Нашу подпись можно отдать на проверку тому, кого мы заменяем, — и вендорский verify её принял. Именно так подтвердилась байт-в-байт совместимость.
- Боевой трафик. Пассивный захват трафика в проде дал 48 записанных пар «настоящий запрос → настоящий ответ». Реплей всех 48 против новой реализации — главный регрессионный тест: 48/48. Синтетические тесты проверяют то, что ты придумал; записанный трафик проверяет то, что бывает.
Отсюда главный вывод кейса: агентская разработка едет ровно настолько, насколько удаётся построить внешний автоматический критерий правоты — оракул. Реверс протокола с живым эталоном рядом — идеальный для этого случай, и этим объясняется, почему «месяцы» сжались в часы.
Независимое ревью
Перед боевым переключением весь код прошёл отдельное ревью — другим агентом, с явной установкой искать плохое. Результат: 0 critical, 2 high — обе исправлены до переключения (лимиты на входные данные против DoS и корректный выбор подписанта при проверке подписи).
Честная оговорка, без которой это была бы реклама: обе high-находки не были найдены тестами — все тесты были зелёными. Их нашло чтение кода, потому что ошибки жили в том, чего в записанном трафике не оказалось. Оракул отвечает на вопрос «совпадаю ли я с эталоном на наблюдавшихся входах» — на вопрос «что будет на входе, которого я не видел» он не отвечает. Скорость дал оракул; безопасность выхода в прод дало ревью.
Переключение с откатом
Новый шлюз развёрнут отдельным деплойментом в Kubernetes. Переключение — смена одного адреса в настройках КРЕ; старый маршрут остался жив как мгновенный откат. Финальная проверка перед переключением — настоящим вендорским клиентом по сети, изнутри кластера. После переключения боевой трафик пошёл через новую реализацию.
Если у вас в контуре сидит похожий компонент — закрытый, без документации, держащий на себе платформу, с которой давно пора уехать, — напишите: расскажу, как мы это делали и с чего начать у вас.