跳转至

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 证书之后

  1. 将由国家根签发的 L1 证书导入 Gerege 的 HSM(证书是公开信息,导入是安全的)。
  2. 在 Gerege 内部创建两个独立的 L2 签发 CA(均由 L1 签发):
  3. Personal(自然人)—— 密钥标签例如 gerege-personal-issuing-ca
  4. Organization(法人)—— 密钥标签例如 gerege-org-issuing-ca 两者均为 pathlen:0。在组织的叶子证书中包含 organizationIdentifier (OID 2.5.4.97,例如 NTRMN-<登记号>)。
  5. Go 服务端配置(同一个服务同时加载两个签发 CA):
  6. SMARTID_PKI_CA_PROVIDER=hsmproxy
  7. Personal: SMARTID_HSMPROXY_KEY_LABEL=<Personal L2 密钥>SMARTID_HSMPROXY_ISSUING_CERT=<Personal L2 证书>
  8. Organization(可选):SMARTID_HSMPROXY_ORG_KEY_LABEL=<Org L2 密钥>SMARTID_HSMPROXY_ORG_ISSUING_CERT=<Org L2 证书>
  9. 自动选择: 依据 ETSI 前缀 —— PNOMN-… → Personal CA,NTRMN-… → Organization CA (domain.SubjectTypeForEtsi + store.caFor)。若未配置 Org,则回退到 Personal。
  10. 叶子证书会附带完整证书链(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 中生成新密钥并签发自签名证书:

  1. 在 HSM 主机上(密钥仪式 —— hsm-thales-gerege/docs/eid-issuing-ca-key-ceremony-script.md):
    cmu generatekeypair -slot <issuing> -lco \
        -keytype rsa -modulusbits 4096 -publicexponent 65537 -mech prime \
        -labelpublic "eidmongol-org-issuing-ca-v1" -labelprivate "eidmongol-org-issuing-ca-v1" \
        -sign 1 -verify 1 -encrypt 0 -decrypt 0 -wrap 0 -unwrap 0 -derive 0
    
    (public/private 标签相同 —— hsm-proxy 按标签查找;请与 Personal 密钥的约定保持一致。)
  2. 从应用主机远程签发证书(无需返回 HSM 主机)—— cmd/hsmca-selfsign 通过代理的 /pubkey/sign-digest 创建自签名 CA 证书:
    hsmca-selfsign -url https://hsm-proxy:8443 -label eidmongol-org-issuing-ca-v1 \
      -client-cert client.crt -client-key client.key -server-ca proxy-ca.crt \
      -subject "CN=eID Mongolia Organization Issuing CA, O=Gerege, C=MN" \
      -years 20 -out org-issuing-ca.crt        # 输出至 deploy/secrets/hsmproxy/
    
  3. .env(应用主机):SMARTID_HSMPROXY_ORG_KEY_LABEL=eidmongol-org-issuing-ca-v1SMARTID_HSMPROXY_ORG_ISSUING_CERT=/app/hsmproxy/org-issuing-ca.crtdocker compose up -d app
  4. 验证:启动日志中出现 “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 密钥仪式(组织不自行生成印章密钥)。

  1. 在 HSM 主机上(每个组织一次,EC P-256): 标签 = <前缀><登记号> (默认前缀 eseal-;例如登记号 1234567 → eseal-1234567):
    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 0
    
    (public/private 标签相同;hsm-proxy 按标签查找。前缀可通过 SMARTID_SEAL_KEY_PREFIX 修改。)
  2. .env(应用主机):SMARTID_SEAL_QSCD=true(hsmproxy CA provider 与 HSMPROXY 凭据 必须已配置就绪 —— 否则服务端会 fail-fast 停止启动,以防止错误地宣称 QSCD)。 若前缀不同,请设置 SMARTID_SEAL_KEY_PREFIX=eseal-
  3. 签发印章证书(管理端或 RP):服务端通过 /pubkey 获取该组织 eseal-<登记号> 标签的公钥,并由 Organization CA 签发证书。私钥始终留在 HSM 中。
  4. 盖章: POST /v3/seal/{orgEtsi} —— 服务端通过 /sign-digest(HSM 密钥)对摘要签名, 并在用证书公钥校验后返回。
  5. 验证:印章证书的 certificateLevel=QSCD;管理端“Organization CA”界面显示 “QSCD (QcSSCD + QCP-l-qscd)”;openssl x509 中可见 QcSSCD 声明与策略 0.4.0.194112.1.3。

若为尚未完成密钥仪式的组织签发印章证书,服务端会从 /pubkey 收到 404 并返回错误 (fail-closed)—— 它不会在宣称 QSCD 的同时悄悄回退为软件密钥。