跳转至

gerege.mn —— eID Gerege 集成(认证 · 签名 · 推送)

本指南介绍如何将 gerege.mn 作为 RP 接入 eID Gerege,通过 App2App(同设备)与 Push(跨设备)流程获得身份认证电子签名能力。通信协议与 Smart-ID 兼容(ACSP_V2)。

RP 通用指南:RP_INTEGRATION.md。本文包含 gerege.mn 的实际配置与可直接复制的示例


0. gerege.mn 的 RP 配置(已注册)

字段 取值
relyingPartyUUID 43a7bda9-0d68-4324-9ec1-3fc6dd8e4edf
relyingPartyName gerege.mn
API secret(Bearer) rp_sk_… —— 从运营方获取,保存在 $GEREGE_RP_SECRET 环境变量中(服务端仅保存 SHA-256 哈希)
RP-API 基础地址 https://rp-api.eidmongolia.mn/v3
回调主机白名单 gerege.mnwww.gerege.mn(App2App 返回 URL 必须是其中之一)
应用 deep-link 协议 geregesmartid://approve?sessionId=…
服务发现 GET https://rp-api.eidmongolia.mn/.well-known/eid

每次调用均需: - 请求头:Authorization: Bearer $GEREGE_RP_SECRET - 请求体:relyingPartyUUIDrelyingPartyNamecertificateLevelQUALIFIED)、signatureProtocolACSP_V2


1. 身份认证 —— App2App(同设备,浏览器与应用位于同一部手机)

当用户用手机访问 gerege.mn 时:创建会话 → 通过 deep-link 打开应用 → 用户输入 PIN 确认 → 应用返回回调地址 → 轮询会话结果。

1.1 创建会话(携带 initialCallbackUrl

curl -sS -X POST https://rp-api.eidmongolia.mn/v3/authentication/device-link/anonymous \
  -H "Authorization: Bearer $GEREGE_RP_SECRET" -H "Content-Type: application/json" \
  -d '{
    "relyingPartyUUID": "43a7bda9-0d68-4324-9ec1-3fc6dd8e4edf",
    "relyingPartyName": "gerege.mn",
    "certificateLevel": "QUALIFIED",
    "signatureProtocol": "ACSP_V2",
    "initialCallbackUrl": "https://gerege.mn/auth/eid/callback?state=<csrf>",
    "interactions": [{"type":"displayTextAndPIN","displayText60":"gerege.mn нэвтрэх"}]
  }'
响应:
{ "sessionID": "…", "sessionToken": "…", "sessionSecret": "…",
  "deviceLinkBase": "https://eidmongolia.mn/dl", "vc": "2025" }

⚠️ initialCallbackUrl 的主机必须位于白名单中(gerege.mn/www.gerege.mn)—— 否则服务端会静默丢弃(防范开放重定向 / 钓鱼)。服务端仅保留 host 与 query, 并将路径强制规范化为 /auth/eid/callback,因此请将 RP 的返回页面放在该路径下。 可将 vc(4 位验证码)显示在 gerege.mn 页面上,供用户与手机上的验证码进行比对。

使用响应中的 sessionID 从浏览器唤起应用:

geregesmartid://approve?sessionId=<sessionID>
应用打开后,用户使用 PIN1(身份认证密钥)确认。随后应用会返回到您的 initialCallbackUrl

1.3 轮询结果 → 见 [§4]


2. 身份认证 —— Push(跨设备:用户位于另一台设备 / 电脑)

若您已知用户的登记号 / civil ID / 设备号,可直接向其手机发送推送。

# 使用 ETSI(PNOMN-<civilId>),或直接使用登记号 / civil ID 推送(服务端会自动识别类型)
curl -sS -X POST https://rp-api.eidmongolia.mn/v3/authentication/notification/etsi/PNOMN-<civilId> \
  -H "Authorization: Bearer $GEREGE_RP_SECRET" -H "Content-Type: application/json" \
  -d '{
    "relyingPartyUUID": "43a7bda9-0d68-4324-9ec1-3fc6dd8e4edf",
    "relyingPartyName": "gerege.mn",
    "certificateLevel": "QUALIFIED",
    "signatureProtocol": "ACSP_V2",
    "interactions": [{"type":"displayTextAndPIN","displayText60":"gerege.mn нэвтрэх"}]
  }'
# → { "sessionID": "…", "vc": { "type":"alphaNumeric4", "value":"2422" } }
vc.value 显示在 gerege.mn 页面上 —— 用户将其与手机收到的推送中的验证码比对后确认。 也可以按 document/{documentNumber}(设备 UUID)发送推送。


3. 电子签名(Signature)—— PIN2,不可否认

文档的 SHA-256 摘要(base64)在手机上使用 PIN2(签名密钥)完成签名。 手机会依据被签名的摘要计算 VC,因此用户看到的验证码即对应被签署的内容(WYSIWYS)。

3.1 通过 Push(跨设备)

DIGEST=$(sha256sum document.pdf | cut -d' ' -f1 | xxd -r -p | base64)
curl -sS -X POST https://rp-api.eidmongolia.mn/v3/signature/notification/document/<documentNumber> \
  -H "Authorization: Bearer $GEREGE_RP_SECRET" -H "Content-Type: application/json" \
  -d "{
    \"relyingPartyUUID\": \"43a7bda9-0d68-4324-9ec1-3fc6dd8e4edf\",
    \"relyingPartyName\": \"gerege.mn\",
    \"certificateLevel\": \"QUALIFIED\", \"signatureProtocol\": \"ACSP_V2\",
    \"digest\": \"$DIGEST\", \"hashType\": \"SHA256\",
    \"interactions\": [{\"type\":\"displayTextAndPIN\",\"displayText60\":\"gerege.mn гарын үсэг\"}]
  }"
# 通过 ETSI:/signature/notification/etsi/PNOMN-<civilId>

3.2 通过 App2App(同设备)

POST /v3/signature/device-link/document/{documentNumber} —— 请求体包含 digesthashTypeinitialCallbackUrl(gerege.mn),随后通过 geregesmartid://approve?sessionId=… 打开应用。

3.3 完成之后 —— PAdES PDF(可选)

一旦轮询返回 endResult=OK,即可对原始 PDF 加盖签章,下载内嵌验证页与 RFC 3161 时间戳的 PDF(PAdES-T):

curl -sS -X POST "https://rp-api.eidmongolia.mn/v3/signature/stamp/<sessionID>?fileName=document.pdf" \
  -H "Authorization: Bearer $GEREGE_RP_SECRET" --data-binary @document.pdf -o signed.pdf
验证:https://eidmongolia.mn/verify/<sessionID>(公开访问;二维码中也包含该链接)。


4. 轮询会话结果(长轮询)

curl -sS "https://rp-api.eidmongolia.mn/v3/session/<sessionID>?timeoutMs=120000" \
  -H "Authorization: Bearer $GEREGE_RP_SECRET"
- state=RUNNING —— 处理中(继续轮询) - state=COMPLETE + result.endResult=OK → - signature.value —— 分离式 ECDSA 签名(signature.signatureAlgorithm=ecdsa-with-SHA256) - cert.value —— 公民的 X.509 证书(auth 或 sign),cert.certificateLevel - state=COMPLETE + 其他 result.endResultUSER_REFUSEDTIMEOUTWRONG_VC 等)→ 被拒绝

认证结果校验(gerege.mn 侧): 将返回的证书链接至 eID Gerege 根 CA (OCSP:discovery 文档中的 endpoints.ocsp),并验证 rpChallenge(若已发送)已包含在签名中。


5. 安全要求(gerege.mn 侧)

  • initialCallbackUrl 必须为 https:// + 白名单主机(gerege.mn/www.gerege.mn)。 其他主机会被静默丢弃。
  • 在回调 URL 中带上 state(CSRF)参数,并在返回时进行校验。
  • API secret 只能保存在后端(切勿暴露在浏览器中)。RP-API 调用为服务端到服务端。
  • 向用户展示 VC 验证码以便与手机比对,可防止中间人钓鱼攻击。
  • 轮询会话的 TTL 为 10 分钟(SMARTID_SESSION_TTL_SECONDS)。

6. 流程简图(App2App 身份认证)

gerege.mn(浏览器)          eID Gerege RP-API              eID Gerege 应用(手机)
  │  POST device-link/anonymous  │                                │
  │  (+ initialCallbackUrl)  ───▶ │  创建会话(校验回调白名单)   │
  │  ◀── sessionID, vc            │                                │
  │  geregesmartid://approve?sessionId=… ───────────────────────▶ │  应用打开
  │                               │                                │  PIN1 → 门限认证
  │                               │  ◀──── commit/prove/finish ─── │
  │  ◀───────── 回调: https://gerege.mn/auth/eid/callback?state=… ── │  (返回)
  │  GET session/{id}(轮询)───▶ │                                │
  │  ◀── COMPLETE, endResult=OK, cert ─│                          │

可运行的客户端示例:web/src/lib/rpclient.ts(TypeScript), 或使用 sdk/typescript/ SDK。