# PR-6: Каркас `crypto-service` — Java + КриптоПро JCP, gRPC по UDS

## Цель

Реализовать сервис криптографических операций по ГОСТ:

- проверка подписи входящих квитанций ЭДО, ответов НРД и сообщений
  от брокеров;
- **серверная подпись действий оператора** в `admin-ui` (ради
  соблюдения SLA 2 мин);
- резервный канал отправки в НРД через WS ONYX напрямую (когда ИШ
  не задействован — упаковка и подпись на нашей стороне);
- криптографические проверки целостности эталонов в MinIO.

## Зависимости

- PR-1 (Go-модели).
- PR-4 (`m2m-core` — реализуем `CryptoVerifier`).
- Внешние: лицензия и дистрибутив КриптоПро CSP + JCP под РЕД ОС.

## Состояние блокеров

Этот PR можно начать **только после**:

- получены лицензии КриптоПро CSP и JCP;
- установлен КриптоПро CSP на dev-ВМ;
- доступны тестовые ключевые контейнеры.

До этого — заглушка с gRPC-протоколом, без реальной криптографии.

## Источники

- `docs/architecture/plan.md` — раздел «Криптография: Go + ГОСТ» и
  «Подпись действий оператора».
- Документация КриптоПро JCP.
- Apache Santuario (XMLDSig).

## Состав PR

### 1. gRPC-протокол

`services/crypto-service/proto/crypto.proto`:

```proto
syntax = "proto3";
package bridge_and_joins.crypto.v1;

service CryptoService {
  // Проверка подписи XMLDSig в пакете ЭДО.
  rpc VerifyXMLDSig(VerifyRequest) returns (VerifyResponse);

  // Подпись XML по ГОСТ — для резервного канала WS ONYX и для
  // действий оператора.
  rpc SignXMLDSig(SignRequest) returns (SignResponse);

  // Health-check.
  rpc Health(HealthRequest) returns (HealthResponse);
}

message VerifyRequest {
  bytes  payload     = 1;  // XML с подписью
  string profile     = 2;  // "guest-gost" | "test3-gost" | "prod-gost" | ...
}

message VerifyResponse {
  bool   valid        = 1;
  string signer_cn    = 2;  // CN из сертификата
  string signer_inn   = 3;  // ИНН из сертификата (если есть)
  string serial       = 4;
  int64  not_before   = 5;  // unix epoch
  int64  not_after    = 6;
  repeated string errors = 7;
}

message SignRequest {
  bytes  payload     = 1;  // канонизированный XML
  string key_alias   = 2;  // алиас ключа в JCP-keystore
  string profile     = 3;
}

message SignResponse {
  bytes  signed_xml  = 1;
}
```

### 2. Java-проект

Структура:
```
services/crypto-service/
├── build.gradle.kts        — Gradle с Liberica JDK 21
├── src/main/java/.../CryptoServer.java       — main, gRPC сервер
├── src/main/java/.../VerifyHandler.java      — Santuario verify
├── src/main/java/.../SignHandler.java        — Santuario sign
├── src/main/java/.../KeystoreProvider.java   — Provider-абстракция
│                                                  (КриптоПро / Валидата / ...)
└── src/test/java/.../*Test.java
```

Зависимости:
- gRPC Java + protoc-gen-java,
- Apache Santuario с ГОСТ-патчем,
- КриптоПро JCP (jar поставляется заказчиком вместе с лицензией).

### 3. Бинд на UDS

Сервер слушает Unix Domain Socket по пути из конфига (`/run/bj/crypto.sock`),
а не TCP — минимальная задержка, изоляция от сети.

### 4. Provider-абстракция

`KeystoreProvider` — интерфейс с реализациями `CryptoProJcpProvider`,
`ValidataJcpProvider` (заглушка), `VipNetProvider` (заглушка). Выбор —
через конфиг (env: `BJ_CRYPTO_PROVIDER=cryptopro`).

### 5. Go-клиент

`internal/cryptocli/client.go`:

Клиент gRPC по UDS, реализует `m2mcore.CryptoVerifier`. Используется
из `lk-gateway` (верификация заявления), `m2m-core` (верификация
квитанций НРД), `nsd-adapter/onyx` (подпись для резервного канала).

### 6. Тесты

- Юнит-тесты Java на эталонах: подпиши тестовым ключом → провер'
  → должен быть `valid=true`.
- Юнит-тесты Go-клиента на mock-сервере gRPC.
- Интеграционный тест (помечен `//go:build integration`): запускает
  crypto-service как процесс и проверяет подпись/проверку
  эталонной квитанции.

### 7. Сборка и упаковка

- `Dockerfile` для `crypto-service` (Liberica JDK 21 base).
- Подключение к `deploy/docker-compose/docker-compose.yml` (mount UDS
  как volume).

## Требования

- **Закрытые ключи КриптоПро никогда не логируются и не выгружаются**
  через API. Только handle на keystore.
- Каждая операция подписи — аудит-запись в журнале (`audit.log` или
  отдельный gRPC stream): кто (оператор/системный ключ), что
  подписано (sha256 от payload), когда.
- Без эмодзи.

## Коммит

```
feat(crypto-service): gRPC-каркас сервиса криптографии (КриптоПро JCP)

- services/crypto-service/proto/crypto.proto — protobuf-контракт
- services/crypto-service/ — Java 21 + gRPC, заглушки Verify/Sign
- internal/cryptocli/ — Go-клиент по UDS, реализует CryptoVerifier
- deploy/docker-compose/docker-compose.yml — подключение сервиса

Реальная подпись КриптоПро подключается после получения лицензии и
ключевых контейнеров от заказчика.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
```

## После коммита

Обновить `docs/tasks/README.md`: PR-6 — «выполнено».
