Gerege eID —— 接入国家 CA(L1 CSR → 证书链)¶
依据法律,Gerege 必须链接到国家根 CA —— 即作为从属 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)。 L1 之下有两个独立的 L2 签发 CA(按用途 / 策略分离)—— 已在真实 HSM 上验证(
TestHSMProxyDualIssuingCA)。
1. L1 CSR —— 内容(已在真实 HSM 上验证)¶
internal/crypto 中的 TestPrepareL1CSR 使用 HSM 密钥生成 L1 CSR(PoP):
Subject: C=MN, O=Gerege Systems LLC, CN=Gerege eID CA
Public-Key: RSA-2048 (2048 位密钥仪式于 7 月;4096 位约一年后)
Requested Extensions:
Basic Constraints: critical, CA:TRUE, pathlen:1 ← 两级结构(L1→L2)**必需**
Key Usage: critical, Certificate Sign, CRL Sign
Signature: sha256WithRSAEncryption (proof-of-possession 校验通过)
请使 Subject DN 符合国家 CA 的命名规则(对方可能要求特定的 O/CN/organizationIdentifier)。上述内容仅为建议。
2. (!)必须从国家 CA 取得的书面确认事项¶
| 事项 | 原因 |
|---|---|
| pathLenConstraint ≥ 1 | 最终 L1 证书的 pathlen 由国家根决定(CSR 只是请求)。若为 0,Gerege 将无法签发 L2 → 两级结构无法成立。请将该条写入从属 CA 协议。 |
| 算法 / 密钥长度 | RSA-2048(当前)—— 须与对方的密钥仪式 / CP-CPS 兼容 |
| 有效期 | L1 的有效期短于根证书 |
| DN / 命名规则 | O/CN/organizationIdentifier |
| CRL/OCSP 规则 | AIA/CDP URL 的指向 |
3. 何时生成真实的 CSR¶
真实的 L1 密钥在正式密钥仪式(7 月,RSA-2048)上生成,需有 M-of-N 密钥保管人、
防拆封袋与见证人 —— 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 证书导入 Gerege 的 HSM(证书是公开信息,导入是安全的)。
- 在 Gerege 内部创建两个独立的 L2 签发 CA(均由 L1 签发):
- Personal(自然人)—— 密钥标签例如
gerege-personal-issuing-ca - Organization(法人)—— 密钥标签例如
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,则回退到 Personal。 - 叶子证书会附带完整证书链(L2+L1);信任锚为国家根 CA。
已在真实 HSM 上验证: -
TestHSMProxy3LayerChain—— 国家根 → L1(pathlen:1)→ L2(pathlen:0)→ 叶子证书。 -TestHSMProxyDualIssuingCA—— L1 → {Personal, Organization} 签发 CA → 两份叶子证书,两条链均验证通过。
云 HSM 故障切换(本地 Luna 故障时自动切换)¶
为避免本地 Luna 会话中断(slot ... not found / CKR_SESSION_HANDLE_INVALID)
导致注册 / 盖章停摆,可配置备用 hsm-proxy(后端为 Thales DPoD Luna Cloud HSM)。
同一把 CA 密钥(相同标签)必须已通过 backup/restore 克隆至 DPoD 分区
(分区配置须与 prodpart1 完全一致 —— hsm-thales-gerege/docs/ceremony-rehearsal-results.md)。
SMARTID_HSMPROXY_FALLBACK_URL=https://<dpod-proxy>:8443 # 基于云 HSM 的 hsm-proxy
SMARTID_HSMPROXY_FALLBACK_CLIENT_CERT=/app/hsmproxy/dpod-client.crt # 留空则沿用主实例的证书
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" 则云端优先(此时需手动把本地设为备用)
- 行为: 主实例不可达或返回 5xx(slot/session)→ 自动切换到备用; 返回 4xx(标签错误)→ 不进行切换。签名会用签发 CA 证书的公钥进行校验 (若备用实例持有错误密钥 → fail-closed)。该规则同样适用于 Personal 与 Organization 签发 CA 以及 e-Seal 客户端。
- 手动切换:
SMARTID_HSMPROXY_PREFER=fallback(需重启)—— 将云端设为主实例。 - 测试:
TestHSMProxyFailover_*(IssuingCA/PreferFallback/BothDown/4xxNoFailover/SealClientEC)。
在生产环境启用 Organization 签发 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通过代理的/pubkey与/sign-digest创建自签名 CA 证书: - .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(hsmproxy CA provider 与 HSMPROXY 凭据 必须已配置就绪 —— 否则服务端会 fail-fast 停止启动,以防止错误地宣称 QSCD)。 若前缀不同,请设置SMARTID_SEAL_KEY_PREFIX=eseal-。 - 签发印章证书(管理端或 RP):服务端通过
/pubkey获取该组织eseal-<登记号>标签的公钥,并由 Organization CA 签发证书。私钥始终留在 HSM 中。 - 盖章:
POST /v3/seal/{orgEtsi}—— 服务端通过/sign-digest(HSM 密钥)对摘要签名, 并在用证书公钥校验后返回。 - 验证:印章证书的
certificateLevel=QSCD;管理端“Organization CA”界面显示 “QSCD (QcSSCD + QCP-l-qscd)”;openssl x509中可见 QcSSCD 声明与策略 0.4.0.194112.1.3。
若为尚未完成密钥仪式的组织签发印章证书,服务端会从 /pubkey 收到 404 并返回错误
(fail-closed)—— 它不会在宣称 QSCD 的同时悄悄回退为软件密钥。