Revert "12"

This reverts commit 2d4eee2950.
This commit is contained in:
Your Name
2026-08-06 04:52:21 +00:00
parent 2d4eee2950
commit 3a217f0dd0
81 changed files with 10766 additions and 0 deletions
+166
View File
@@ -0,0 +1,166 @@
# chestny-znak-web-app — План реализации тестового web-приложения для API Честного знака
**Статус:** Активен
## Описание задачи
Проанализировать API «Честный знак» (ГИС МТ, True API) и создать план реализации тестового web-приложения, которое позволяет:
1. Авторизоваться в системе (подписать тестовый набор данных УКЭП)
2. Получить информацию о QR-кодах (КМ) из УПД — актуальны или нет
## Результаты анализа API
### Документация True API
| Параметр | Значение |
|----------|----------|
| Официальная документация | https://docs.crpt.ru/gismt/True_API/ |
| Тестовый контур (sandbox) | `https://markirovka.sandbox.crptech.ru/api/v3/true-api` |
| Промышленный контур | `https://markirovka.crpt.ru/api/v3/true-api` |
| Версия API | v3/v4 |
| Формат | REST, JSON |
| Аутентификация | УКЭП (ГОСТ, CAdES-BES) → Bearer token |
### Процесс аутентификации (Единая аутентификация)
```
Шаг 1: GET /auth/key → { uuid, data }
(получаем UUID и случайную строку для подписи)
Шаг 2: Подписать data УКЭП (CAdES-BES, присоединённая подпись, base64)
(требуется КриптоПро или совместимое СКЗИ)
Шаг 3: POST /auth/simpleSignIn → { token, uuidToken?, expireDate? }
Body: { uuid: "<uuid>", data: "<base64 signature>" }
```
- Срок действия токена: **не более 10 часов**
- Форматы токена: JWT (по умолчанию) или UUID (параметр `unitedToken: true`)
- Поддержка JWT — до марта 2026 года, UUID — основной формат
### Ключевые методы для задачи
| Метод | Endpoint | Описание |
|-------|----------|----------|
| Получение информации о КМ | `POST /api/v3/true-api/cises/info` | Статус, производитель, собственник, GTIN |
| Проверка кодов (розница) | `POST /api/v4/true-api/codes/check` | Проверка перед продажей |
| Публичная проверка | `GET https://mobile.api.crpt.ru/mobile/check?code=<код>` | Без авторизации (недокументированный эндпоинт моб. приложения) |
| Поиск КМ | `POST /api/v4/true-api/cises/search` | Поиск по фильтрам |
### Пример публичного API (без авторизации)
Запрос:
```
GET https://mobile.api.crpt.ru/mobile/check?code=0104640507713421215TxdVFoOB.zFF
```
Ответ (JSON):
```json
{
"code": "0104640507713421215TxdVFoOB.zFF",
"found": true,
"valid": true,
"status": "INTRODUCED"
}
```
**Ограничения публичного API:**
- Не требует аутентификации — можно использовать для быстрой проверки единичных кодов
- Возвращает минимум данных: только статус и флаг валидности
- Не подходит для пакетной проверки (по одному коду за запрос)
- Не документирован официально (эндпоинт мобильного приложения)
**Для полноценной проверки КМ из УПД рекомендуется использовать авторизованный метод** `POST /api/v3/true-api/cises/info`, который возвращает полную информацию: GTIN, наименование товара, производителя, владельца, дату ввода в оборот и т.д.
### Структура ответа /cises/info
```json
{
"cisInfo": [{
"requestedCis": "0104600702028445...",
"cis": "0104600702028445...",
"gtin": "04600702028445",
"status": "INTRODUCED",
"productName": "Молоко 3.2%",
"productGroup": "Молочная продукция",
"producerName": "АО \"Данон Россия\"",
"ownerName": "ООО Магнит",
"ownerBin": "2309085638",
"producedDate": "2025-01-15T10:00:00.000Z",
"packageType": "UNIT"
}]
}
```
**Статусы КМ:** `EMITTED` (эмитирован), `APPLIED` (нанесён), `INTRODUCED` (в обороте), `RETIRED` (выбыл), `WRITTEN_OFF` (списан), `DISAGGREGATION` (расформирован), `CANCELLED` (аннулирован)
### Работа с УПД
- Коды маркировки в XML УПД (формат Приказа №970 ФНС) находятся в элементе `Документ/ТаблСчФакт/СведТов/ДопСведТов/НомСредИдентТов`
- При проверке QR-кодов из УПД необходимо:
1. Загрузить XML УПД (формат 970 приказа)
2. Распарсить XML по XPath: `//Документ/ТаблСчФакт/СведТов/ДопСведТов/НомСредИдентТов`
3. Извлечь все коды маркировки
4. Отправить запрос в `/cises/info` (с авторизацией)
5. Отобразить статус каждого кода
---
## Шаги
- [ ] 1. **Инициализация проекта** — создать Fastify/Express backend + React frontend. Оба сервиса запускаются через `docker-compose`
- [ ] 2. **Backend: модуль аутентификации**
- 2.1. Реализовать `GET /auth/key` — получение UUID + data от True API
- 2.2. Реализовать подпись data через КриптоПро с помощью `@vgoma/crypto-pro` (Node.js binding для КриптоПро CSP)
- 2.3. Реализовать `POST /auth/simpleSignIn` — получение токена
- 2.4. Кеширование и auto-refresh токена (раз в 10 часов)
- [ ] 3. **Backend: модуль проверки КМ**
- 3.1. Реализовать `POST /api/check-codes` — принимает массив кодов маркировки
- 3.2. Вызов `POST /api/v3/true-api/cises/info` для каждого кода (батчами до 1000)
- 3.3. Возврат статуса: актуален / неактуален / не найден / ошибка
- [ ] 4. **Backend: модуль обработки УПД**
- 4.1. Приём XML-файла УПД через `POST /api/upload-upd`
- 4.2. Парсинг XML, извлечение кодов маркировки из `НомСредИдентТов`
- 4.3. Передача кодов в модуль проверки КМ (шаг 3)
- [ ] 5. **Frontend: страница авторизации**
- 5.1. Форма ввода/загрузки сертификата УКЭП
- 5.2. Отображение статуса авторизации и срока действия токена
- [ ] 6. **Frontend: страница проверки QR-кодов**
- 6.1. **Проверка одного кода** — поле ввода + две кнопки:
- «Проверить без авторизации» — через публичный API (`mobile.api.crpt.ru/mobile/check`), минимум данных
- «Проверить с авторизацией» — через `POST /cises/info`, полная информация: GTIN, наименование, производитель, владелец, статус
- 6.2. **Загрузка XML УПД (формат 970 приказа)** — drag & drop / file picker, парсинг на backend, пакетная проверка через `/cises/info`
- 6.3. Таблица результатов: код, GTIN, наименование, статус, производитель, владелец
- 6.4. Цветовая индикация: зелёный (актуален / в обороте), красный (выбыл / списан), жёлтый (предупреждение)
- [ ] 7. **Тестирование на sandbox**
- 7.1. Получение тестового УКЭП через testca2012.cryptopro.ru
- 7.2. Регистрация в sandbox (markirovka.sandbox.crptech.ru)
- 7.3. Интеграционные тесты: авторизация → проверка кодов
- [ ] 8. **Docker-сборка**
- 8.1. `Dockerfile.backend` — backend-образ с Node.js + установленным КриптоПро CSP (`crypto-pro`)
- 8.2. `Dockerfile.frontend` — nginx-образ со статикой React-приложения
- 8.3. `docker-compose.yml` — сервисы `backend`, `frontend`, общая сеть
- 8.4. README с инструкцией по запуску (`docker-compose up --build`)
- [x] 9. **Переключение контура (sandbox/prod) из UI**
- 9.1. Backend: два набора URL (`envUrls`) в `config.ts`, per-env кеш токенов
- 9.2. Backend: все сервисы и роуты принимают `?env=sandbox|prod`
- 9.3. Frontend: `<select>` в хедере, `getEnv()`/`setEnv()` в модуле API
- 9.4. QA-доработки:
- `onUnauthorized` передаёт env — логаут правильного контура при 401
- `window.confirm` при переключении на промышленный контур
- `setPage('auth')` при смене env
- `getAuthStatus` при переключении — восстановление `authenticated` если токен жив
- `uploadUpd` через общий `request()` (устранено дублирование)
## Затрагиваемые сервисы
- `backend/` — Fastify/Express backend с модулями:
- `auth-service` — получение и менеджмент токена True API
- `crypto-service` — подпись данных через `@vgoma/crypto-pro` (КриптоПро CSP)
- `cises-service` — проверка статусов кодов маркировки через `/cises/info`
- `upd-parser` — парсинг XML УПД и извлечение кодов
- `frontend/` — React (Next.js) SPA:
- Страница авторизации
- Страница проверки кодов
- Компонент загрузки УПД
+85
View File
@@ -0,0 +1,85 @@
# connect-sandbox — Подключение к песочнице API Честного знака
**Статус:** Активен
## Описание
План действий для подключения к тестовому контуру (sandbox) API Честного знака (True API) и выполнения первого успешного запроса. Код приложения уже реализован — требуется выполнить шаги регистрации, получения тестового УКЭП и запуска.
## Шаги
### 1. Регистрация в sandbox Честного знака
- [ ] 1.1. Перейти на портал sandbox: https://markirovka.sandbox.crptech.ru/
- [ ] 1.2. Зарегистрировать участника (юридическое лицо или ИП)
- [ ] 1.3. Создать тестовую учётную запись организации
- [ ] 1.4. Убедиться, что организация активна в sandbox
### 2. Получение тестового УКЭП
- [ ] 2.1. Перейти на testca2012.cryptopro.ru
- [ ] 2.2. Скачать тестовый сертификат для физического лица (или сгенерировать через КриптоПро CSP)
- [ ] 2.3. Установить сертификат в личное хранилище (Настройки → КриптоПро CSP → Сертификаты)
- [ ] 2.4. Убедиться, что сертификат имеет статус «Действителен»
- [ ] 2.5. Связать тестовый сертификат с зарегистрированной организацией в sandbox (если требуется)
### 3. Установка КриптоПро Browser Plugin
- [ ] 3.1. Скачать КриптоПро Browser Plugin: https://cryptopro.ru/products/cades/plugin
- [ ] 3.2. Установить плагин в браузер (поддерживаются Chrome, Firefox, Edge, Chromium)
- [ ] 3.3. Перезапустить браузер
- [ ] 3.4. Проверить установку: открыть `chrome://plugins/` (или `about:addons`) — плагин должен быть активен
### 4. Настройка и запуск приложения
- [ ] 4.1. Склонировать репозиторий (если ещё не):
```bash
git clone <url>
cd chestno-api
```
- [ ] 4.2. Проверить конфигурацию `backend/.env`:
```env
TRUE_API_URL=https://markirovka.sandbox.crptech.ru/api/v3/true-api
PUBLIC_CHECK_URL=https://mobile.api.crpt.ru/mobile/check
```
- [ ] 4.3. Запустить приложение:
```bash
docker-compose up --build
```
- [ ] 4.4. Проверить, что сервисы запущены:
- Backend: http://localhost:3002/health
- Frontend: http://localhost:3003
### 5. Авторизация в sandbox через приложение
- [ ] 5.1. Открыть http://localhost:3003
- [ ] 5.2. Убедиться, что страница авторизации показывает «КриптоПро Browser Plugin: Обнаружен»
- [ ] 5.3. Выбрать тестовый сертификат из списка
- [ ] 5.4. Нажать «Подписать и войти»
- [ ] 5.5. Проверить, что получен токен и отображается статус «Авторизован» с TTL
### 6. Проверка работоспособности
- [ ] 6.1. Ввести тестовый КМ на странице проверки кодов
- [ ] 6.2. Нажать «Проверить с авторизацией»
- [ ] 6.3. Убедиться, что возвращается полная информация о КМ (GTIN, статус, производитель, владелец)
- [ ] 6.4. Проверить публичную проверку (без авторизации) — должна работать всегда
## Затрагиваемые сервисы
- `backend/.env` — проверка/корректировка `TRUE_API_URL` на sandbox (уже установлен по умолчанию)
- Внешние:
- **testca2012.cryptopro.ru** — тестовый УЦ для получения сертификата
- **markirovka.sandbox.crptech.ru** — sandbox API Честного знака
- **КриптоПро Browser Plugin** — расширение для браузера (CAdES)
- **КриптоПро CSP** — если требуется для установки сертификата
## Примечания
- Sandbox URL по умолчанию уже настроен в `backend/.env` — код менять не нужно
- В sandbox доступны только тестовые коды маркировки (их можно получить в личном кабинете sandbox)
- JWT-токены отключены с марта 2026 — приложение использует UUID-токены (`unitedToken: true`)
- Для промышленного контура потребуется:
1. Реальный УКЭП юридического лица (ФНС/УЦ)
2. Регистрация в ГИС МТ как участник
3. Смена `TRUE_API_URL` на `https://markirovka.crpt.ru/api/v3/true-api`
+476
View File
@@ -0,0 +1,476 @@
# service-ukep — Выпуск и подключение обезличенной УКЭП (служебной учётной записи) для True API
**Статус:** Активен
## Предпосылки
В текущей архитектуре приложения аутентификация в True API выполняется через УКЭП **физического лица** (сотрудника) с помощью КриптоПро Browser Plugin на стороне клиента. Это означает, что:
- Для каждого сеанса нужен человек с токеном
- Нельзя организовать полностью автоматический обмен (сервер-сервер)
- При увольнении сотрудника доступ теряется
Для автоматической интеграции требуется **обезличенная УКЭП (ОУКЭП)** — сертификат на организацию, без привязки к физлицу.
---
## 1. Юридические основания
| Нормативный акт | Описание |
|-----------------|----------|
| **63-ФЗ ст. 5 п. 2** | Допускается УКЭП, в сертификате которой не указано физлицо (обезличенная), для автоматического создания/проверки ЭП |
| **Приказ ФНС от 08.06.2021 № ЕД-7-24/538@** | Порядок выдачи обезличенных сертификатов УЦ ФНС |
| **443-ФЗ от 01.09.2024** | КЭП оформляется только на директора (без доверенности); для автоматизации — только ОУКЭП |
ОУКЭП применяется для электронных документов, **автоматически формируемых и представляемых** в ГИС МТ, за исключением:
- Заявления о регистрации участника
- Заявки на тестирование
- Заявки на доступ к устройству регистрации эмиссии
---
## 2. Сравнение вариантов
| Характеристика | ОУКЭП (обезличенная) | КЭП физлица + МЧД | API-ключ (x-api-key) |
|----------------|----------------------|--------------------|---------------------|
| **Кому выдаётся** | Организации (без физлица) | Физлицу | Организации (в ЛК) |
| **Без человека** | ✅ Да — полный автомат | ❌ Нет — нужен человек с токеном | ✅ Да |
| **Срок** | 15 месяцев | 12-15 месяцев | до 01.07.2026 (продление?) |
| **Доступ к True API** | ✅ Полный | ✅ Полный | ❌ Только касса (розн. режим) |
| **Стоимость** | 0 ₽ (УЦ ФНС) / 3–10 тыс. ₽ (коммерч.) | ~3 000 ₽/год | 0 ₽ |
| **Риски** | Низкие | Увольнение сотрудника | Ограниченный функционал |
**Вывод:** для серверной интеграции с True API требуется именно ОУКЭП.
---
## 3. Порядок выпуска ОУКЭП через УЦ ФНС (бесплатно)
### 3.1. Подготовка документов
| № | Документ | Примечание |
|---|----------|------------|
| 1 | **Письмо-заявление** на официальном бланке организации | С обоснованием: «для автоматического обмена с ГИС МТ через True API» |
| 2 | **Копия распорядительного документа** о создании информационной системы | Приказ о вводе в эксплуатацию информационной системы, осуществляющей автоматический обмен |
| 3 | **Паспорт руководителя** (оригинал) | Личная явка в УЦ ФНС |
| 4 | **СНИЛС руководителя** | |
| 5 | **ИНН организации + ИНН руководителя** | |
| 6 | **Выписка из ЕГРЮЛ** | Свежая (не старше 1 мес.) |
| 7 | **Решение о назначении руководителя** | Протокол / приказ |
| 8 | **USB-токен** | Рутокен ЭЦП 3.0 или JaCarta-2 ГОСТ (см. п. 3.2) |
**Образцы документов:**
- Письмо-заявление: https://github.com/romangorbenko/OUKEP/blob/main/letter.docx
- Приказ о создании ИС: https://github.com/romangorbenko/OUKEP/blob/main/order.docx
- Приказ о назначении ответственного: https://github.com/romangorbenko/OUKEP/blob/main/ResponsibleAppointment.docx
### 3.2. Требования к носителю (2026 год)
С 1 апреля 2026 все КЭП — только по новым ГОСТ 34.12-2018 / 34.13-2018.
| Носитель | Статус |
|----------|--------|
| **Рутокен ЭЦП 3.0** | ✅ Работает |
| **JaCarta-2 ГОСТ** | ✅ Работает |
| **JaCarta-3** | ✅ Работает |
| Рутокен ЭЦП 2.0 | ❌ Устарел (не принимается) |
| Рутокен Lite | ❌ Не сертифицирован |
| eToken (старые) | ❌ Не сертифицированы |
### 3.3. Процесс получения
```mermaid
graph TD
A[Подготовить документы] --> B[Записаться в УЦ ФНС]
B --> C[Личная явка руководителя с паспортом + токеном]
C --> D[Выпуск сертификата на носитель]
D --> E[Установка КриптоПро CSP 5.0+]
E --> F[Импорт сертификата в хранилище]
```
1. Записаться в ближайшую ИФНС, оказывающую услуги УЦ (перечень на nalog.gov.ru)
2. Явиться лично с комплектом документов и USB-токеном
3. Сотрудник УЦ проверяет документы, идентифицирует личность, выпускает сертификат
4. Получить носитель с записанным сертификатом
5. **Срок:** от 1 часа до 3 рабочих дней
6. **Срок действия:** 15 месяцев
### 3.4. Альтернатива — коммерческий УЦ
| УЦ | Ориентировочная стоимость | Примечание |
|----|---------------------------|------------|
| Контур (ca.kontur.ru) | ~5 000–8 000 ₽/год | Удалённо, курьер |
| Такском (taxcom.ru) | ~4 000–7 000 ₽/год | Удалённо |
| СБИС (sbis.ru) | ~5 000–10 000 ₽/год | Удалённо |
| Астрал (astral.ru) | ~3 000–6 000 ₽/год | Удалённо |
**Плюсы:** не нужна личная явка в ФНС, быстрее, сопровождение.
**Минусы:** платно.
---
## 4. Техническая подготовка к автоматической подписи (сервер)
### 4.1. Схема работы
```
Сервер (Linux)
├── КриптоПро CSP 5.0 R2+ ← подпись УКЭП
├── Носитель с ОУКЭП
│ ├── Физический USB (Рутокен) → через USB-over-IP (NIO-EUSB / Digi AnywhereUSB)
│ └── Или виртуальный (копия ключа, если разрешено политикой)
├── Наше приложение (backend)
│ ├── got → True API (auth/key, simpleSignIn)
│ └── crypto-pro (или КриптоПро CLI) → подпись data
└── Хранилище сертификатов (/var/opt/cprocsp/...)
```
### 4.2. Требования к серверу
| Компонент | Версия | Назначение |
|-----------|--------|------------|
| **ОС** | Linux (x86_64) | Рекомендуется Ubuntu 22.04+/Debian 12+/Astra Linux |
| **КриптоПро CSP** | 5.0.12000+ (5.0 R2) | Криптопровайдер |
| **КриптоПро CLI (cryptcp)** | из состава CSP | Генерация запросов, подпись |
| **lsb-cprocsp-devel** | из состава CSP | Разработка |
| **USB-токен** | Рутокен ЭЦП 3.0 / JaCarta-2 ГОСТ | Носитель ключа |
| **pcscd** | любая | Демон для работы с USB-токенами |
| **Node.js** | 20+ | Наше приложение |
### 4.3. Установка КриптоПро CSP на сервер
```bash
# 1. Скачать дистрибутив с cryptopro.ru (требуется авторизация)
# linux-amd64_deb.tgz
# 2. Установить
tar -xzf linux-amd64_deb.tgz
cd linux-amd64_deb
./install.sh
# 3. Проверить установку
/opt/cprocsp/sbin/cryptopro -v
# 4. Установить лицензию
/opt/cprocsp/bin/cryptopro -setkey <license-key>
# 5. Подключить токен (через USB или USB-over-IP)
# Убедиться, что pcscd запущен
systemctl start pcscd
# 6. Проверить видимость токена
/opt/cprocsp/bin/cryptopro -list
```
### 4.4. Генерация запроса на сертификат (PKCS#10)
Если ОУКЭП выпускается через УЦ ФНС **впервые** (без готового носителя), нужно сгенерировать запрос на сервере и передать его в УЦ.
**Сгенерировать контейнер и запрос:**
```bash
/opt/cprocsp/bin/cryptcp -createrqst /tmp/request.req \
-rdn "CN=\"ООО \"\"РОМАШКА\"\"\", E=admin@company.ru, C=RU, S=\"77 г. Москва\", L=\"Москва\", STREET=\"ул. Ленина д.1\", O=\"ООО \"\"РОМАШКА\"\"\", 1.2.643.100.4=7700123456, 1.2.643.100.1=1234567890123" \
-pin "" \
-provtype 80 \
-provname "Crypto-Pro GOST R 34.10-2012 Cryptographic Service Provider" \
-certusage 1.3.6.1.5.5.7.3.2 \
-ext RemoteCertificate.ext
```
Где:
- `1.2.643.100.4` — ИНН организации (10 цифр)
- `1.2.643.100.1` — ОГРН (13 цифр или 15 для ИП)
- `RemoteCertificate.ext` — файл с OID для удалённого выпуска (без личной явки) — [скачать шаблон](https://raw.githubusercontent.com/romangorbenko/OUKEP/main/RemoteCertificate.ext)
Файл `request.req` передаётся в УЦ ФНС (на USB-флешке, вместе с пакетом документов из п. 3.1).
### 4.5. Установка полученного сертификата на сервер
```bash
# Установить сертификат в контейнер
/opt/cprocsp/bin/cryptcp -inst \
-cont "\\.\A-<идентификатор контейнера>" \
-cert /tmp/certificate.cer
# Проверить
/opt/cprocsp/bin/cryptopro -list
```
### 4.6. Подпись данных (автоматическая)
**Вариант A — через CLI (cryptcp):**
```bash
echo -n "$DATA" | base64 -d > /tmp/data_to_sign.bin
/opt/cprocsp/bin/cryptcp -sign \
-detached \
-thumbprint <THUMBPRINT> \
/tmp/data_to_sign.bin /tmp/signature.sig
cat /tmp/signature.sig | base64 -w0
```
**Вариант B — через Node.js binding (`@vgoma/crypto-pro`):**
Пакет `@vgoma/crypto-pro` умеет работать с КриптоПро CSP на сервере (не только в браузере). Требует установленного CSP и библиотеки `lsb-cprocsp-devel`.
```typescript
import { createAttachedSignature } from '@vgoma/crypto-pro'
const signature = await createAttachedSignature(thumbprint, base64data)
```
**Вариант C — через REST-сервис КриптоПро (CryptoPro DSS):**
КриптоПро предоставляет DSS (Digital Signature Service) — REST API для подписи. Устанавливается как отдельный сервис.
### 4.7. Дооснащение backend-контейнера (`backend/Dockerfile`)
Текущий Dockerfile использует `node:20-alpine`. Для работы с КриптоПро потребуется:
```dockerfile
# Вариант: переход на образ с КриптоПро CSP
FROM node:20-bookworm AS builder
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY src/ ./src/
RUN npm run build
FROM node:20-bookworm AS runner
WORKDIR /app
# Установка КриптоПро CSP
COPY cprocsp/*.deb /tmp/
RUN dpkg -i /tmp/*.deb || true
RUN apt-get install -f -y && \
/opt/cprocsp/sbin/cryptopro -setkey <license>
# Установка НЦА (сертификаты УЦ)
RUN /opt/cprocsp/sbin/cpverify -install ...
# USB-over-IP клиент (если токен не локальный)
COPY nio-eusb-client /usr/local/bin/
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
EXPOSE 3001
CMD ["node", "dist/index.js"]
```
**Или проще:** использовать готовый образ от КриптоПро или развернуть сервис подписи на отдельной ВМ, а наш backend будет вызывать его по REST.
---
## 5. Регистрация ОУКЭП в личном кабинете Честного знака
### 5.1. Для True API (ГИС МТ)
После получения сертификата его нужно зарегистрировать в ГИС МТ:
1. Войти в ЛК Честного знака: https://markirovka.crpt.ru (с УКЭП руководителя)
2. Перейти: **Профиль → Администрирование → Учётные системы**
3. Нажать **«Добавить учётную систему»**
4. Указать наименование (например, «Сервер интеграции API»)
5. В карточке учётной системы нажать **«Добавить сертификат»**
6. Загрузить **открытую часть сертификата** (файл .cer)
**Важно:** для каждого контура (sandbox / prod) регистрация выполняется отдельно.
### 5.2. Внутренний распорядительный акт (обязательно)
Требование 63-ФЗ: издать приказ о назначении **ответственного лица** за автоматическое создание/проверку ЭП в информационной системе.
Документ должен содержать:
- ФИО сотрудника, ответственного за автоматическую подпись
- Регламент работы информационной системы
- Порядок действий при компрометации ключа
Без этого акта использование ОУКЭП юридически недействительно.
---
## 6. Техническая интеграция — изменения в приложении
### 6.1. Изменение архитектуры
Сейчас подпись выполняется **на клиенте** (в браузере через CadesPlugin). После внедрения ОУКЭП:
```
Схема А: только серверная подпись (рекомендуется)
─────────────────────────────────────
Frontend (браузер) Backend (наш сервер) True API
│ │ │
│ GET /auth/key │ │
│───────────────────────────────>│ │
│ │ GET /auth/key │
│ │──────────────────────────────>│
│ │<────────────────────────────── │
│ { uuid, data } │ │
│<───────────────────────────────│ │
│ │ │
│ POST /auth/simpleSignIn │ (подпись на сервере) │
│ { uuid } │ через КриптоПро CSP │
│───────────────────────────────>│ │
│ │ POST /auth/simpleSignIn │
│ │ { uuid, data: <sign> } │
│ │──────────────────────────────>│
│ │<────────────────────────────── │
│ { token } │ │
│<───────────────────────────────│ │
```
**Изменения:**
- Frontend отправляет только `{ uuid }` (без data)
- Backend сам подписывает data через установленный КриптоПро CSP
- Browser Plugin на стороне клиента больше **не нужен** для авторизации
- Весь процесс аутентификации — на backend
### 6.2. Модификация backend-сервисов
**`auth-service.ts`:**
```typescript
import { execSync } from 'child_process'
function signData(dataBase64: string): string {
const thumbprint = process.env.CERT_THUMBPRINT
// Вариант 1: через CLI cryptcp
const result = execSync(
`/opt/cprocsp/bin/cryptcp -sign -detached -thumbprint ${thumbprint} /dev/stdin /dev/stdout`,
{ input: Buffer.from(dataBase64, 'base64') }
)
return result.toString('base64')
// Вариант 2: через @vgoma/crypto-pro (асинхронно)
// return createAttachedSignature(thumbprint, dataBase64)
}
export async function getAuthKey(env: TrueApiEnv): Promise<AuthKeyResponse> {
// ... без изменений
}
export async function serverSignIn(env: TrueApiEnv): Promise<AuthSignInResponse> {
const { uuid, data } = await getAuthKey(env)
const signature = signData(data)
return signIn(env, { uuid, data: signature })
}
```
**Новый endpoint:**
```typescript
// POST /auth/server-login — полная авторизация на backend
app.post('/auth/server-login', async (request, reply) => {
const env = parseEnv(request.query)
try {
const result = await serverSignIn(env)
return result
} catch (err) {
// обработка ошибок
}
})
```
### 6.3. Необходимые файлы
| Файл | Назначение |
|------|------------|
| `backend/certs/certificate.cer` | Открытая часть сертификата ОУКЭП |
| `backend/Dockerfile` | Установка КриптоПро CSP + импорт сертификата |
| `backend/src/services/crypto-service.ts` | Сервис подписи через КриптоПро |
| `.env` / secrets | `CERT_THUMBPRINT`, лицензия КриптоПро |
### 6.4. Переменные окружения (добавить в .env)
```env
# Режим аутентификации: client (через браузер) или server (через ОУКЭП)
AUTH_MODE=server
# Отпечаток сертификата ОУКЭП
CERT_THUMBPRINT=<sha1-thumbprint>
# Только для AUTH_MODE=server:
# Путь к файлу открытой части сертификата (для валидации)
CERT_FILE=/app/certs/certificate.cer
```
---
## 7. Пошаговый план действий
### Этап 1. Подготовка документов
- [ ] 1.1. Подготовить письмо-заявление на бланке организации
- [ ] 1.2. Подготовить приказ о создании информационной системы
- [ ] 1.3. Подготовить приказ о назначении ответственного за автоматическую подпись
- [ ] 1.4. Собрать остальные документы (паспорт, СНИЛС, ИНН, выписка ЕГРЮЛ)
- [ ] 1.5. Приобрести Рутокен ЭЦП 3.0 или JaCarta-2 ГОСТ
### Этап 2. Получение ОУКЭП
- [ ] 2.1. Записаться в УЦ ФНС (или выбрать коммерческий УЦ)
- [ ] 2.2. Явиться лично с документами и носителем
- [ ] 2.3. Получить сертификат на носитель
- [ ] 2.4. Скопировать открытую часть сертификата (.cer)
### Этап 3. Регистрация в Честном знаке
- [ ] 3.1. Войти в ЛК Честного знака
- [ ] 3.2. Создать учётную систему в разделе Администрирование
- [ ] 3.3. Загрузить сертификат в учётную систему
- [ ] 3.4. Повторить для sandbox-контура (при необходимости)
### Этап 4. Настройка сервера
- [ ] 4.1. Установить КриптоПро CSP 5.0 R2 на сервер
- [ ] 4.2. Подключить токен с ОУКЭП (локально или через USB-over-IP)
- [ ] 4.3. Импортировать сертификат, проверить видимость
- [ ] 4.4. Установить корневые сертификаты Минцифры и УЦ ФНС
- [ ] 4.5. Проверить подпись через CLI: `cryptcp -sign`
### Этап 5. Доработка приложения
- [ ] 5.1. Реализовать `crypto-service.ts` — подпись через КриптоПро CSP
- [ ] 5.2. Добавить endpoint `POST /auth/server-login`
- [ ] 5.3. Добавить переменные окружения (`AUTH_MODE`, `CERT_THUMBPRINT`)
- [ ] 5.4. Обновить `Dockerfile` — установка КриптоПро CSP
- [ ] 5.5. Обновить `docker-compose.yml` — проброс USB-токена (если локальный)
- [ ] 5.6. Обновить frontend — кнопка «Авторизация сервера» (для режима server)
### Этап 6. Тестирование
- [ ] 6.1. Проверить авторизацию в sandbox через серверную подпись
- [ ] 6.2. Проверить получение токена
- [ ] 6.3. Проверить проверку КМ с новым токеном
- [ ] 6.4. Проверить auto-refresh токена (каждые 10 часов)
- [ ] 6.5. Проверить обработку ошибок (невалидная подпись, просрочка сертификата)
---
## 8. Ссылки
| Ресурс | URL |
|--------|-----|
| Официальная документация True API | https://docs.crpt.ru/gismt/True_API/ |
| Статья на Хабре (подробный гайд) | https://habr.com/ru/articles/838390/ |
| Образцы документов (Github) | https://github.com/romangorbenko/OUKEP |
| Письмо-заявление (шаблон) | https://github.com/romangorbenko/OUKEP/blob/main/letter.docx |
| Приказ о создании ИС (шаблон) | https://github.com/romangorbenko/OUKEP/blob/main/order.docx |
| КриптоПро CSP | https://cryptopro.ru/products/csp |
| База знаний Честного знака (ОУКЭП) | https://markirovka.ru/knowledge/tovarnye-gruppy/obschie-voprosy-gis/ispolzovanie-obezlichennykh-ukep |
| Добавление ОУКЭП в учётную систему | https://markirovka.ru/knowledge/lekarstva/api-mdlp/upravlenie-obezlichennymi-ukep-dobavlenie-obezlichennoy-ukep |
| Реестр аккредитованных УЦ Минцифры | https://digital.gov.ru/ru/activity/469/ |
---
## Затрагиваемые сервисы
- `backend/Dockerfile` — установка КриптоПро CSP 5.0, импорт сертификатов
- `backend/docker-compose.yml` — возможно, проброс USB-устройства
- `backend/src/services/crypto-service.ts` — **новый файл**, сервис подписи данных
- `backend/src/services/auth-service.ts` — добавление `serverSignIn()`
- `backend/src/routes/auth.ts` — новый endpoint `POST /auth/server-login`
- `backend/.env` — новые переменные `AUTH_MODE`, `CERT_THUMBPRINT`
- `backend/certs/` — **новая директория** с открытой частью сертификата
- `frontend/src/pages/AuthPage.tsx` — кнопка «Авторизация сервера» (опционально)