Gerege eID —— 标识符(ETSI ID 与登记号)¶
系统中有两个用于标识个人 / 组织的主要号码:ETSI 标识符(证书中的标准键) 与登记号(РД)(蒙古国公民号)。本文说明二者的结构与含义。
1. ETSI 标识符 —— etsi_identifier¶
ETSI = European Telecommunications Standards Institute(欧洲电信标准协会)。我们的
etsi_identifier 即 ETSI EN 319 412-1 标准中的 “semantics identifier”,
也就是将国家号码写入证书的国际标准格式。它符合 eIDAS,并与爱沙尼亚 Smart-ID 的
semanticsIdentifier 在协议层兼容(我们在其基础上做了适配)。
格式¶
PNOMN-95103015
└┬┘└┬┘ └───┬──┘
│ │ └── 实际号码(自然人为 civil_id —— 仅数字,而非 РД)
│ └── 国家 —— ISO 3166-1 alpha-2(MN = 蒙古国)
└── 主体类型(3 个字符)
| 前缀 | 含义 | 归属 | 示例 |
|---|---|---|---|
| PNO | Person Number(国家个人号码) | 自然人(Natural Person) | PNOMN-95103015 |
| NTR | National Trade Register(国家商事登记) | 组织(Legal Person) | NTRMN-1234567 |
为什么这样设计¶
- 稳定的主键: 每位公民的设备 / 证书 / 会话都通过该 ID 关联
(
users.etsi_identifier为主键)。 - 符合标准: 这是将国家 ID 写入 eIDAS 合格证书的规范做法;欧洲的 RP 能够识别。
- 类型内嵌于前缀:
PNO↔NTR区分自然人与组织 → 用于自动选择签发 CA (domain.SubjectTypeForEtsi,Personal/Organization CA)。 - 内部取值为
civil_id(仅数字)而非 РД: 证书的SERIALNUMBER字段是 X.509 PrintableString,无法容纳西里尔字母的 РД。因此自然人取PNOMN-<civil_id>(etsi = "PNOMN-" + civilID);РД 是users表中的独立属性,不会写入证书。
代码位置:
persistence.UserAccount.EtsiIdentifier、domain.SubjectTypeForEtsi、crypto_wired.go中的 ETSI 构造("PNOMN-" + civilID)。
2. 登记号(РД)—— registration_number¶
蒙古国公民的登记号:2 个西里尔字母 + 8 位数字(例如 УБ95103015)。
结构(名义上)¶
出生日期 / 性别 —— 来源与从 РД 推导¶
date_of_birth 与 gender 首先直接来自 KYC 核验方(DAN/eMongolia)
(service.KycResult.DateOfBirth、.Gender;经 DAN 回调通过 NormalizeGender 处理)。
部分来源(G-Sign)不会返回这些字段 —— 证书 subject 只提供身份信息。这种情况下,
系统会从 РД 推导(util.BirthAndGenderFromRegNo、gsign/kycverifier.go):
- 日期: 前 6 位数字 = YYMMDD。月份为 21..32 → 2000 年之后(年份 2000+YY,月份 MM-20);
月份为 01..12 → 2000 年之前(年份 1900+YY)。若为无效日历日期 → nil。
- 性别: 倒数第 2 位为奇数 → "M",偶数 → "F"(与日期无关)。
若数字缺失或格式错误,则各自留空(nil/"")—— 留空胜过错误的猜测。
3. 其他相关号码¶
| 字段 | 说明 | 来源 |
|---|---|---|
civil_id |
公民身份证号(不必与 РД 一致) | KYC(KycResult.CivilID) |
| 组织登记号 | 法人的国家登记 → etsi NTRMN-<...>、organizationIdentifier(OID 2.5.4.97) |
KYC(KycResult.OrgRegister) |
document_number |
每台设备的唯一 UUID(不含 РД —— 保护隐私)。即 Smart-ID 的 documentNumber | 由服务端生成 |
certificates.serial_number |
X.509 序列号(十进制);在 OCSP/CRL 中为十六进制 | CA |
原则: 公民 / 组织的身份属性(civil_id、组织登记号、姓名)一律来自 KYC 核验方 (DAN/eMongolia)—— 不从号码推导,也不凭空编造。若来源未提供,则留空。 (出生日期 / 性别通常来自 KYC;来源不返回时才从 РД 推导,见 §2。)
小结¶
- ETSI 标识符 = “把国家号码写入证书的标准格式”(
PNOMN-…为自然人,NTRMN-…为组织)。名称拗口,但含义简单。 - РД = “2 个字母 + 8 位数字”的公民号。出生日期 / 性别通常直接来自 KYC 来源;
否则从 РД 推导(
util.BirthAndGenderFromRegNo)。
§Case —— 身份文本的大小写规则¶
规则: 身份文本在数据库中的规范形式为小写;所有检索 / 过滤 / 比较均按小写进行; 展示时转换为标准形式。用户输入登记号时可使用任意大小写。
适用字段(人工录入 / 来自 KYC 的身份文本):
users.registration_number(РД)、civil_id、given_name、surname、full_name。
| 操作 | 规则 | 实现 |
|---|---|---|
| 存储 | trim + lower(小写规范形式) | util.NormalizeIdentity;recordUserAndCert;KYC normalizeRegNo=lower |
| 检索 / 查找 / 比较 | 先将输入规范化为小写再比较(不区分大小写) | pg FindByIdentifier/Search reg_no → lower;inmem 已为小写;DAN 回调匹配为 lower-lower |
| 展示 | РД → 大写(util.DisplayRegNo);西里尔姓名 → Title Case(util.TitleCaseName) |
PersonBlock、PersonSummary、admin userView、KYC 预览 |
不适用(拥有各自的协议 / PKI 规范形式 —— 请勿改动):
- etsi_identifier —— ETSI EN 319 412-1 规范(PNOMN-…/NTRMN-…);查找 / 比较使用大写。
- 证书 SERIALNUMBER / subject DN、given_name_latin/surname_latin —— ICAO/eIDAS 大写。
- document_number(UUID)、API 密钥哈希、组织 org_register(数字)、组织 name(专有名词)。
原因: 各 KYC 来源返回的大小写各不相同(DAN 为 “ЭРДЭНЭБАТ”,G-Sign 为 “баярсайхан”), 用户书写 РД 时可能写成 “УБ…” 或 “уб…”。统一采用一种规范形式(小写)后,查找与去重才能保持一致; 展示时再转换为标准形式。拉丁字母 / etsi / 证书拥有各自的规范形式,因此不受本规则约束。