Gerege eID — подключение к национальному CA (L1 CSR → цепочка)¶
По закону Gerege обязан выстраивать цепочку до национального корневого CA — то есть быть подчинённым CA, а не самостоятельным корнем. Итоговая иерархия:
Национальный корневой CA (государственный HSM) └── Gerege CA (L1) — национальный корень подписывает ТОЛЬКО его; pathlen:1 ├── Gerege Personal Issuing CA (L2, pathlen:0) → сертификат физического лица └── Gerege Organization Issuing CA (L2, pathlen:0) → сертификат юридического лицаТерминология eIDAS: Personal = Natural Person, Organization = Legal Person. Два отдельных выпускающих CA уровня L2 под L1 (разделены по назначению/политике) — проверено на реальном HSM (
TestHSMProxyDualIssuingCA).
1. L1 CSR — содержимое (проверено на реальном HSM)¶
TestPrepareL1CSR в internal/crypto формирует L1 CSR ключом HSM (PoP):
Subject: C=MN, O=Gerege Systems LLC, CN=Gerege eID CA
Public-Key: RSA-2048 (церемония — июль 2048; 4096 примерно годом позже)
Requested Extensions:
Basic Constraints: critical, CA:TRUE, pathlen:1 ← ОБЯЗАТЕЛЬНО для 2-уровневой схемы (L1→L2)
Key Usage: critical, Certificate Sign, CRL Sign
Signature: sha256WithRSAEncryption (проверка proof-of-possession OK)
Приведите Subject DN в соответствие с правилами именования национального CA (они могут требовать конкретные O/CN/organizationIdentifier). Приведённое выше — рекомендация.
2. (!) Что необходимо получить ПИСЬМЕННО от национального CA¶
| Пункт | Зачем |
|---|---|
| pathLenConstraint ≥ 1 | Значение pathlen в итоговом сертификате L1 определяет национальный корень (CSR лишь запрашивает). Если будет 0, Gerege не сможет выпускать L2 → двухуровневая схема НЕ РАБОТАЕТ. Зафиксируйте это в соглашении о подчинённом CA. |
| Алгоритм / размер ключа | RSA-2048 (сейчас) — должен быть совместим с их церемонией/CP-CPS |
| Срок действия | L1 короче корневого |
| Правила DN / именования | O/CN/organizationIdentifier |
| Правила CRL/OCSP | Куда указывают URL AIA/CDP |
3. КОГДА генерировать настоящий CSR¶
Настоящий ключ L1 генерируется на официальной церемонии ключей (июль, RSA-2048)
с M-of-N хранителями, tamper-пакетами и свидетелями —
hsm-thales-gerege/docs/eid-issuing-ca-key-ceremony-script.md.
Демо-ключ использовать нельзя. Во время церемонии CSR формируется одним из двух способов:
A. Go (hsm-proxy, этот репозиторий): по метке ключа, созданного на церемонии,
HSMPROXY_E2E_URL=https://<proxy>:8443 HSMPROXY_E2E_CERT=admin.crt HSMPROXY_E2E_KEY=admin.key \
CSR_OUT=gerege-l1.csr go test ./internal/crypto -run TestPrepareL1CSR -v
# (измените тест так, чтобы метка соответствовала ключу церемонии; ВНИМАНИЕ: демо удаляет ключ)
B. Нативный Luna (cmu, совместим со сценарием церемонии):
cmu requestcertificate -slot <issuing> -lco \
-publichandle <ph> -privatehandle <prh> \
-sha256withrsa -outputfile gerege-l1.csr \
-cn "Gerege eID CA" -o "Gerege Systems LLC" -c MN
cmuне помещает расширения в CSR — pathlen/keyUsage национальный корень выставляет по договорённости.
4. После получения сертификата L1¶
- Импортируйте сертификат L1, подписанный национальным корнем, в HSM Gerege (сертификат публичный, это безопасно).
- Внутри Gerege создайте два отдельных выпускающих CA уровня L2 (каждый подписан L1):
- Personal (Natural Person) — метка ключа, например
gerege-personal-issuing-ca - Organization (Legal Person) — метка ключа, например
gerege-org-issuing-caУ каждогоpathlen:0. В листовом сертификате организации —organizationIdentifier(OID 2.5.4.97, например NTRMN-<регистр>). - Конфигурация Go-сервера (один сервер загружает оба выпускающих CA одновременно):
SMARTID_PKI_CA_PROVIDER=hsmproxy- Personal:
SMARTID_HSMPROXY_KEY_LABEL=<ключ Personal L2>,SMARTID_HSMPROXY_ISSUING_CERT=<сертификат Personal L2> - Organization (опционально):
SMARTID_HSMPROXY_ORG_KEY_LABEL=<ключ Org L2>,SMARTID_HSMPROXY_ORG_ISSUING_CERT=<сертификат Org L2> - Автоматический выбор: по префиксу ETSI —
PNOMN-…→ Personal CA,NTRMN-…→ Organization CA (domain.SubjectTypeForEtsi+store.caFor). Если Org не сконфигурирован, происходит fallback на Personal. - к листовому сертификату прикрепляется полная цепочка (L2+L1); якорь доверия = национальный корень.
Проверено на реальном HSM: -
TestHSMProxy3LayerChain— национальный корень → L1 (pathlen:1) → L2 (pathlen:0) → лист. -TestHSMProxyDualIssuingCA— L1 → {Personal, Organization} issuing CA → два листа, обе цепочки проверяются успешно.
Failover на Cloud HSM (автоматическое переключение при отказе on-prem Luna)¶
Чтобы регистрация и печать не останавливались при обрыве сессии on-prem Luna
(slot ... not found / CKR_SESSION_HANDLE_INVALID), можно настроить резервный hsm-proxy
(за Thales DPoD Luna Cloud HSM). Тот же ключ CA (с той же меткой) должен быть склонирован
в раздел DPoD через backup/restore (конфигурация раздела должна совпадать с prodpart1 —
hsm-thales-gerege/docs/ceremony-rehearsal-results.md).
SMARTID_HSMPROXY_FALLBACK_URL=https://<dpod-proxy>:8443 # hsm-proxy на базе Cloud HSM
SMARTID_HSMPROXY_FALLBACK_CLIENT_CERT=/app/hsmproxy/dpod-client.crt # если пусто, берётся от primary
SMARTID_HSMPROXY_FALLBACK_CLIENT_KEY=/app/hsmproxy/dpod-client.key
SMARTID_HSMPROXY_FALLBACK_SERVER_CA=/app/hsmproxy/dpod-proxy-ca.crt
SMARTID_HSMPROXY_PREFER=primary # "fallback" ставит Cloud НА ПЕРВОЕ место (on-prem выбирается как резерв вручную)
- Поведение: если primary недоступен или возвращает 5xx (slot/session) → автоматический переход на fallback; при 4xx (неверная метка) failover не выполняется. Подпись проверяется публичным ключом сертификата выпускающего CA (fallback с неверным ключом → fail-closed). Правило одинаково действует для Personal и Organization issuing CA, а также для клиента e-Seal.
- Ручное переключение:
SMARTID_HSMPROXY_PREFER=fallback(с перезапуском) — делает Cloud основным. - Тесты:
TestHSMProxyFailover_*(IssuingCA/PreferFallback/BothDown/4xxNoFailover/SealClientEC).
Включение Organization issuing CA в продакшене (на этапе БЕЗ национального корня)¶
Текущий продуктивный Personal CA (eidmongol-issuing-ca-v1) самоподписан (национальный L1 ещё
не существует). Organization CA настраивается так же — новый ключ + самоподписанный сертификат в HSM:
- На хосте HSM (церемония — hsm-thales-gerege/docs/eid-issuing-ca-key-ceremony-script.md): (метки public/private ОДИНАКОВЫ — hsm-proxy ищет по метке; соблюдайте соглашение ключа Personal.)
- Выпустите сертификат удалённо с хоста приложения (возвращаться на хост HSM не нужно) —
cmd/hsmca-selfsignсоздаёт самоподписанный сертификат CA через/pubkeyи/sign-digestпрокси: - .env (хост приложения):
SMARTID_HSMPROXY_ORG_KEY_LABEL=eidmongol-org-issuing-ca-v1,SMARTID_HSMPROXY_ORG_ISSUING_CERT=/app/hsmproxy/org-issuing-ca.crt→docker compose up -d app. - Проверка: в логе запуска «HSM-proxy Organization CA enabled»,
GET /crl/orgвозвращает 200, а при выпуске сертификата печати из админки издателем указан Organization CA.
Позже, когда национальный корень будет готов, оба CA будут переподписаны L1 (см. §2 выше).
Превращение e-Seal в QSCD (листовой ключ печати в HSM)¶
По умолчанию листовой ключ e-Seal генерируется на сервере (программный HSM, AES-GCM в БД),
поэтому его уровень — QUALIFIED. Чтобы получить настоящий QSCD (QcSSCD + политика
QCP-l-qscd), каждый ключ печати должен оставаться внутри HSM, а закрытый ключ никогда не должен
попадать на сервер. Модель та же, что и у выпускающего CA: ключ создаётся на HSM в ходе церемонии,
а сервер работает только через /pubkey и /sign-digest.
Модель: e-Seal — это управляемая (контрактная) услуга, как у SK: оператор проводит отдельную церемонию ключей HSM для каждой организации (организация сама ключ печати не создаёт).
- На хосте HSM (для каждой организации, EC P-256): метка =
<префикс><регистрационный код>(префикс по умолчаниюeseal-; например, регистр 1234567 →eseal-1234567):(метки public/private ОДИНАКОВЫ; hsm-proxy ищет по метке. Префикс меняется черезcmu generatekeypair -slot <issuing> -lco \ -keytype ec -curve prime256v1 \ -labelpublic "eseal-1234567" -labelprivate "eseal-1234567" \ -sign 1 -verify 1 -encrypt 0 -decrypt 0 -wrap 0 -unwrap 0 -derive 0SMARTID_SEAL_KEY_PREFIX.) - .env (хост приложения):
SMARTID_SEAL_QSCD=true(CA-провайдер hsmproxy и учётные данные HSMPROXY должны быть уже настроены — иначе сервер выполнит fail-fast и остановится, чтобы не объявлять QSCD ложно). Если префикс другой —SMARTID_SEAL_KEY_PREFIX=eseal-. - Выпуск сертификата печати (админ или RP): сервер получает публичный ключ метки
eseal-<код>этой организации через/pubkeyи выпускает сертификат через Organization CA. Закрытый ключ остаётся в HSM. - Проставление печати:
POST /v3/seal/{orgEtsi}— сервер подписывает дайджест через/sign-digest(ключ HSM) и возвращает подпись, проверенную публичным ключом сертификата. - Проверка: у сертификата печати
certificateLevel=QSCD; на экране «Organization CA» в админке — «QSCD (QcSSCD + QCP-l-qscd)»; вopenssl x509— statement QcSSCD и политика 0.4.0.194112.1.3.
Если попытаться выпустить сертификат печати для организации, для которой церемония НЕ проводилась,
сервер получит от /pubkey ответ 404 и вернёт ошибку (fail-closed) — он не станет молча
переключаться на программный ключ, объявляя при этом QSCD.