统一身份认证系统国家标准
统一身份认证系统国家标准这条线,很多人第一句就问错:问的是"有没有一份专门叫统一身份认证系统的国标"。实际上不存在这样一份单独的标准,评审现场对的是一组要求——等级保护里的身份鉴别与访问控制条款、商用密码应用安全性评估里的四个技术层面、个人信息保护相关的分类分级与最小必要。某高校在一次评审中被指出"身份平台未落实国标要求",追问之下,问题出在票据没带受众、密钥三年没轮换。这类偏差很典型。
坐标先立:身份平台要对的标准可以按"合规要求—技术层面—密钥管理"三层来拆。最上层是网络安全法、数据安全法、个人信息保护法与等保、密评给出的义务;中间一层是 GB/T 22239-2019 与 GB/T 39786-2021 给的技术与管理要求;最下一层是密钥全生命周期管理,它决定前两层能不能举证。本文切入的是最容易被做浅的一块:统一身份认证系统国家标准这条线,怎么从"条款"翻译成"可验证的动作"。
01 | 统一身份认证系统国家标准这件事,难在哪儿
统一身份认证系统国家标准相关的工作,难点不在找不到标准,而在"条款说得很抽象、举证要求很具体"。某制造企业的身份平台上线两年,功能齐备,评审时却拿不出一份能对上条款的证据清单。具体难在下面五处。
首要难点在统一身份认证系统实施案例里的做法不能直接抄。每个组织的系统构成、定级、数据敏感度都不同;照抄别人的实施方案,最常见的结果是条款对上一半、另一半对不上。
其次,条款与技术动作之间没有现成映射。"应采用密码技术进行身份鉴别"这句话,落到工程上是挑战-应答签名、票据签名、时效校验三件事;测评不会告诉你映射关系,得自己建表。
再有一处难点在统一身份认证系统密钥管理方案被当成运维事项。密钥生成、存储、分发、轮换、销毁这五件事,评审是当技术核查项来查的;当成运维,就没人准备证据。
还有一处难点在票据设计不完整。票据带了主体、带了有效期,却没有受众;同一张票据在多个业务系统之间可以随便用,评审问"怎么防止越权使用",答不上来。
最后一处难点在轮换没有记录。密钥三年没换,或者换过但没有记录;评审要求提供轮换周期与最近一次轮换时间,交付方只能翻聊天记录。
把这五处串起来看,核心矛盾是:标准给的是"要做什么",而评审要的是"做了没有的证据",中间那一层翻译没人做。
02 | 机制拆解:统一身份认证系统国家标准的四条线
统一身份认证系统实施案例反复印证的一点是:先把四条线各自的职责划清楚,再看它们怎么共用一套密钥。
| 线 | 对应条款方向 | 要落实的动作 | 缺了会怎样 |
|---|---|---|---|
| 身份鉴别 | 等保身份鉴别、密评身份鉴别 | 挑战-应答、票据签名 | 凭据可被伪造 |
| 访问控制 | 等保访问控制、密评访问控制 | 票据带受众与时效,三选三校验 | 票据跨系统通兑、过期仍可用 |
| 密钥管理 | 密评密钥管理、等保剩余信息保护 | 分层派生、周期轮换、记录留存 | 一把密钥用到底、无从举证 |
| 审计留痕 | 等保安全审计 | 台账整体签名、不可篡改 | 记录可改、说不清 |
四条线的边界要讲清楚:身份鉴别只解决"你是谁",访问控制解决"这张票据能在哪儿用",密钥管理解决"前面两件事的密钥从哪来、怎么用、什么时候换",审计留痕是前三件事的证据来源。四者共用一套密钥体系,才能串成一条链。
统一身份认证系统国家标准里的身份鉴别线
身份鉴别线的落点是"挑战-应答 + 票据签名"。口令只在初始化阶段用于解锁私钥,日常登录走挑战值签名;票据由身份平台用域密钥签发,业务系统用对应域公钥验签。这里要强调的是,票据必须整体签名——只签主体标识的话,把有效期改长照样能验过。
统一身份认证系统国家标准里的访问控制线
访问控制线的落点是"三选三校验"。业务系统拿到票据以后,要同时验签名、验受众、验时效:签名不对说明不是本平台签的,受众不对说明这张票据不是发给本系统的,时效不对说明过期了。三条任何一条不过都要拒绝。这一步把"访问控制"从口头规定变成可核查的事实。
统一身份认证系统国家标准里的密钥管理线
密钥管理线的落点是"分层派生 + 周期轮换"。根密钥在硬件密码机内产生与存放,按业务域派生域密钥,再按用途派生票据密钥;轮换时换根,派生链路整体变化,新旧密钥并存一段时间以便平滑切换。这一层是前两条线能否举证的前提。
下面这张图说明四条线的位置关系:
[根密钥:硬件密码机内] --> [按业务域派生域密钥] --> [按用途派生票据密钥] | v [登录请求] --> [挑战-应答签名] --> [签发票票:sub+aud+有效期整体签名] | v [业务系统校验] --> [验签名 + 验受众 + 验时效:三选三] --> [任一不过即拒绝] | v [审计台账:周期/签发数/拒绝数/轮换时间] --> [SM3摘要+SM2整体签名]03 | 先跑通:统一身份认证系统国家标准的四个环节
下面这段演示把票据三选三校验、跨系统不可通兑、分层派生、轮换、台账签名串在同一段代码里跑一遍,用的都是公开算法:SM2 签名、SM3 摘要、SM4 分组加密。代码只依赖gmssl,可以直接复现。
# -*- coding: utf-8 -*- """ W39 Day1 #3 · 统一身份认证系统国家标准(标准符合性 + 密钥管理) 演示:票据三选三校验 / 按业务域派生密钥不可跨系统通兑 / 分层派生 / 轮换 / 台账整体签名 """ from gmssl import sm2, sm4, sm3, func PRIV_EDU = "6a3a91c46a3a91c46a3a91c46a3a91c46a3a91c46a3a91c46a3a91c46a3a91c4" # 教务域 PRIV_LIB = "5b8e27d05b8e27d05b8e27d05b8e27d05b8e27d05b8e27d05b8e27d05b8e27d0" # 图书馆域(另一业务域) PRIV_ROGUE = "4d5f0c724d5f0c724d5f0c724d5f0c724d5f0c724d5f0c724d5f0c724d5f0c72" # 冒名签发方 PRIV_AUDIT = "7c4019ab7c4019ab7c4019ab7c4019ab7c4019ab7c4019ab7c4019ab7c4019ab" FIXED_K = "0101010101010101010101010101010101010101010101010101010101010101" def pub_of(priv: str) -> str: """P = d·G。gmssl 不会从私钥派生公钥,必须显式算出再传给 CryptSM2。""" return sm2.CryptSM2(private_key=priv, public_key="")._kg( int(priv, 16), sm2.default_ecc_table["g"]) PUB_EDU = pub_of(PRIV_EDU) PUB_LIB = pub_of(PRIV_LIB) PUB_ROGUE = pub_of(PRIV_ROGUE) PUB_AUDIT = pub_of(PRIV_AUDIT) def sm3_hex(data: bytes) -> str: return sm3.sm3_hash(func.bytes_to_list(data)) # ---- 手写 SM4-CBC:gmssl 的 crypt_cbc 有缺陷,one_round 是 16 进 16 出的单块运算 ---- def sm4_cbc(key: bytes, iv: bytes, data: bytes, enc: bool) -> bytes: assert len(key) == 16, "SM4 KEY 必须 16 字节" assert len(iv) == 16, "IV 必须 16 字节(少一字节会 IndexError)" c = sm4.CryptSM4() c.set_key(key, sm4.SM4_ENCRYPT if enc else sm4.SM4_DECRYPT) out, prev = b"", iv for i in range(0, len(data), 16): blk = data[i:i + 16] if enc: x = bytes(a ^ b for a, b in zip(blk, prev)) e = bytes(c.one_round(c.sk, list(x))) out += e prev = e else: d = bytes(c.one_round(c.sk, list(blk))) out += bytes(a ^ b for a, b in zip(d, prev)) prev = blk return out def pkcs7_pad(data: bytes, block: int = 16) -> bytes: pad = block - (len(data) % block) return data + bytes([pad]) * pad def pkcs7_unpad(data: bytes) -> bytes: pad = data[-1] if not (1 <= pad <= 16): return data return data[:-pad] # ======================================================================= # # 业务逻辑区 # ======================================================================= # sm2_edu = sm2.CryptSM2(public_key=PUB_EDU, private_key=PRIV_EDU) sm2_lib = sm2.CryptSM2(public_key=PUB_LIB, private_key=PRIV_LIB) sm2_rogue = sm2.CryptSM2(public_key=PUB_ROGUE, private_key=PRIV_ROGUE) sm2_audit = sm2.CryptSM2(public_key=PUB_AUDIT, private_key=PRIV_AUDIT) # --- 1) 票据:主体 + 受众 + 有效期,三样一起进签名 --- NOW = 20260929 ticket = "iss=idp-01|sub=S2021001|aud=edu|nb=20260929|na=20260930" h_t = sm3_hex(ticket.encode("utf-8")) sig_t = sm2_edu.sign(h_t.encode("utf-8"), FIXED_K) ok_sign = sm2_edu.verify(sig_t, h_t.encode("utf-8")) h_t_tam = sm3_hex(ticket.replace("aud=edu", "aud=admin").encode("utf-8")) ok_tamper = not sm2_edu.verify(sig_t, h_t_tam.encode("utf-8")) sig_rogue = sm2_rogue.sign(h_t.encode("utf-8"), FIXED_K) ok_imposter = not sm2_edu.verify(sig_rogue, h_t.encode("utf-8")) # --- 2) 跨系统不可通兑:教务域签的票据,图书馆域公钥验不过 --- ok_cross_domain = not sm2_lib.verify(sig_t, h_t.encode("utf-8")) # --- 3) 时效:有效期已过的票据直接拒绝(逻辑判定) --- def ticket_ok(t: str, aud: str, now: int) -> bool: d = dict(kv.split("=") for kv in t.split("|")) return d["aud"] == aud and int(d["na"]) >= now ok_aud_ok = ticket_ok(ticket, "edu", NOW) ok_aud_bad = not ticket_ok(ticket, "lib", NOW) ok_expired = not ticket_ok("iss=idp-01|sub=S2021001|aud=edu|nb=20260101|na=20260102", "edu", NOW) # --- 4) 分层派生:根密钥 -> 业务域密钥 -> 票据密钥 --- ROOT = b"ROOT-KEY-IN-HSM-2026" def derive(master: bytes, label: str) -> str: return sm3_hex(master + b"|label=" + label.encode("utf-8"))[:32] dom_edu = bytes.fromhex(derive(ROOT, "domain=edu")) dom_lib = bytes.fromhex(derive(ROOT, "domain=lib")) tk_edu = bytes.fromhex(derive(dom_edu, "ticket-v3")) ok_derive_det = derive(ROOT, "domain=edu") == derive(ROOT, "domain=edu") ok_derive_domain = dom_edu != dom_lib ok_derive_not_root = sm3_hex(ROOT)[:32] != dom_edu.hex() ok_keylen = len(tk_edu) == 16 # --- 5) 轮换:根密钥换了以后派生链路全变 --- ROOT2 = b"ROOT-KEY-IN-HSM-2027" ok_rotate_change = bytes.fromhex(derive(ROOT2, "domain=edu")) != dom_edu # --- 6) 台账整体签名 --- ledger = "period=2026Q3|tickets=40213|rejected=37|rotate=20260901" h_l = sm3_hex(ledger.encode("utf-8")) sig_l = sm2_audit.sign(h_l.encode("utf-8"), FIXED_K) ok_ledger = sm2_audit.verify(sig_l, h_l.encode("utf-8")) h_l_t = sm3_hex(ledger.replace("rejected=37", "rejected=0").encode("utf-8")) ok_ledger_tamper = not sm2_audit.verify(sig_l, h_l_t.encode("utf-8")) ok_hash_len = len(h_t) == 64 asserts = [ ("票据签名验签通过", ok_sign), ("票据受众被改后签名被拒绝", ok_tamper), ("冒名签发方签的票据被拒绝", ok_imposter), ("教务域票据在图书馆域验不过", ok_cross_domain), ("受众匹配的票据判定为可用", ok_aud_ok), ("受众不匹配的票据被拒绝", ok_aud_bad), ("有效期已过的票据被拒绝", ok_expired), ("同因子派生可复现", ok_derive_det), ("不同业务域派生密钥不同", ok_derive_domain), ("派生密钥不等于根密钥", ok_derive_not_root), ("票据密钥长度为 16 字节", ok_keylen), ("根密钥轮换后派生链路变化", ok_rotate_change), ("台账签名验签通过", ok_ledger), ("台账被改后签名被拒绝", ok_ledger_tamper), ("SM3 摘要为 64 位十六进制", ok_hash_len), ] # 首行必须是 '='*60:脚本靠它把「demo 输出块」与「ASCII 机制图」区分开 print("=" * 60) for t, ok in asserts: print(f"[{t}] = {'True' if ok else 'False'}")============================================================ [票据签名验签通过] = True [票据受众被改后签名被拒绝] = True [冒名签发方签的票据被拒绝] = True [教务域票据在图书馆域验不过] = True [受众匹配的票据判定为可用] = True [受众不匹配的票据被拒绝] = True [有效期已过的票据被拒绝] = True [同因子派生可复现] = True [不同业务域派生密钥不同] = True [派生密钥不等于根密钥] = True [票据密钥长度为 16 字节] = True [根密钥轮换后派生链路变化] = True [台账签名验签通过] = True [台账被改后签名被拒绝] = True [SM3 摘要为 64 位十六进制] = True逐段读一下这段代码在验什么。第 13 条验票据签名:正常签名能验过,把受众字段改掉、换一把签发私钥,都要被拒——这里用换私钥构造冒名,只改字段验的是完整性而不是身份。第 4 条验跨系统不可通兑:教务域签的票据,拿到图书馆域的公钥下去验,验不过。第 57 条验三选三:受众匹配判定可用、受众不匹配拒绝、有效期已过拒绝。第 811 条验分层派生:同因子可复现、不同业务域派生密钥不同、派生值不等于根密钥、票据密钥是 16 字节。第 12 条验轮换:根密钥换了以后派生链路整体变化。第 1314 条验台账:整体签名能验过,把拒绝数从 37 改成 0 就被拒。第 15 条确认摘要是 64 位十六进制。
现场演示时最能说明问题的是第 4 条和第 7 条:把教务的票据拿到图书馆去验、把过期的票据拿来用,两次都应该直接失败。这两条把"跨系统不可通兑"和"时效"从文档里的词变成了可演示的事实。
要注意一处工程细节:演示里用的是固定 K 的 SM2 签名,目的是让每次输出一致、便于复现;真实系统里签名随机数必须由密码模块内部产生,同一私钥配同一个 K 会泄露私钥。
04 | 落地动作:统一身份认证系统国家标准分四条线怎么做
统一身份认证系统实施案例给出的真正价值是改造顺序,而不是可照抄的配置;统一身份认证系统国家标准的落地,建议按四条线分开推进,每条线给一个可验收的动作。
身份鉴别这条线,动作是建映射表:把每一条要求翻译成具体动作,再注明由哪个系统、用哪个算法、留哪份记录。验收点:随机挑一条要求,能在五分钟内找到对应的证据文件。
访问控制这条线,动作是补票据的受众字段并把校验改成三选三。业务系统拿到票据后,先验签、再比对受众是否为自己、最后看有效期;三条任何一条不过即拒绝。验收点:把教务签发的票据送到图书馆系统,必须被拒。
统一身份认证系统密钥管理方案这条线,动作是做分层派生并记录轮换。根密钥放硬件密码机,按业务域与用途派生;定好轮换周期,每次轮换记录时间、影响范围与并存期。验收点:换根以后,派生链路全变,且记录可查。
留痕这条线,动作是把周期台账整体签名。每个周期记录签发数、拒绝数、轮换时间,算摘要后签名;改一个数字即失败。验收点:改台账里的拒绝数,验签失败。
整改样本(某高校)。背景:身份平台功能齐备但举证困难,票据无受众、密钥三年未轮换。动作:先建要求映射表(两周),再补票据受众字段并把业务系统校验改成三选三(五周),然后做密钥分层派生与轮换记录(四周),最后把周期台账改为整体签名(两周)。结果:随机抽查的条款都能在五分钟内找到证据,跨系统票据被拒、过期票据被拒、台账改一个数字即验签失败,评审结论由"部分符合"转为"符合",总周期约三个半月。真正花时间的是业务系统侧的校验改造,不是身份平台本身。
05 | 避坑清单:8 条最容易踩的坑
| # | 坑 | 后果 | 怎么验证避开了 |
|---|---|---|---|
| 1 | 找"一份叫统一身份认证系统的国标" | 方向一开始就错 | 按三层拆:法规—标准—密钥 |
| 2 | 照抄别人的实施方案 | 条款只对上一半 | 先建本组织的要求映射表 |
| 3 | 票据不带受众 | 跨系统通兑、越权可用 | 送错系统的票据必须被拒 |
| 4 | 只验签不验时效 | 过期票据仍可用 | 过期票据必须被拒 |
| 5 | 只签主体标识 | 有效期可被改长 | 改一个字段即验签失败 |
| 6 | 密钥不轮换 | 无从举证、风险累积 | 有周期、有记录、可查 |
| 7 | 一把密钥全系统通用 | 一个域出问题全受影响 | 按业务域派生、互不可解 |
| 8 | 台账可改 | 评审追问即露馅 | 整体签名,改一个数字即失败 |
| 9 | 演示沿用固定 K | 私钥有泄露风险 | 随机数由密码模块产生 |
| 10 | 轮换不做并存期 | 切换期大面积验签失败 | 新旧密钥并存一段时间 |
展开说第 3 条。票据不带受众是最省事也最危险的设计:一张票据签出来,所有业务系统都认,接入新系统零成本。代价是"越权"这件事在系统里根本没有落点——评审问"怎么防止 A 系统的凭据拿到 B 系统用",答案是防不住。补一个受众字段、在校验侧加一次字符串比对,改造量通常以人日计;但它换来的是访问控制这一层面真正成立。
06 | 合规视角:统一身份认证系统国家标准要对上哪些要求
统一身份认证系统国家标准要对的要求,集中在下面几条。网络安全法与数据安全法。前者确立等级保护制度,后者要求对数据进行分类分级保护。身份平台作为承载全员身份数据的系统,通常是定级对象;定级结论直接决定后面按哪一级的要求准备证据。
网络安全等级保护(GB/T 22239-2019)。三级系统对身份鉴别、访问控制、安全审计、剩余信息保护均有要求。落到身份平台就是:登录凭据要可验证、票据要受控、审计记录要不可修改、密钥与凭据在存储与销毁环节要有保护。
商用密码应用安全性评估(GB/T 39786-2021)。关注身份鉴别、访问控制、数据完整性、数据保密性四个层面的密码技术应用,以及密钥管理。前面四条线正是这四层面加密钥管理的落地;测评会追问算法、密钥生成与存放方式、轮换周期,这些必须写进密码应用方案。
个人信息保护法与 GB/T 35273。身份数据属于个人信息,采集与使用要遵循最小必要;票据里的主体标识建议用持久匿名标识而不是学号这类可直接识别的字段。
统一身份认证系统实施案例里最值得参考的是这张映射表:不要把这些要求当成几份独立清单分别应对,而是建一张映射表,把每条要求映射到"挑战-应答签名、三选三校验、分层派生与轮换、整体签名台账"这四个动作上。一次建设,几份清单同时受益。
07 | 落地答案:统一身份认证系统国家标准怎么承接
统一身份认证系统国家标准的落地,落到产品能力上通常这样组合四条线。
身份鉴别这一段,需要的能力是"统一签发入口 + SM2 整体签名"。统一身份认证平台承接凭据与票据的签发,签名字段清单由方案定死;签发私钥由密钥服务平台托管,根密钥在硬件密码机内。
访问控制这一段,需要的能力是"票据带受众与时效 + 业务侧三选三校验"。票据签发时写入受众与有效期,业务系统先验签、再比对受众、最后校验时效;任一条不过即拒绝,拒绝记录进审计台账。
统一身份认证系统密钥管理方案这一段,需要的能力是"分层派生 + 周期轮换 + 记录留存"。集中密钥管理系统以根密钥为起点,按业务域与用途派生;轮换时换根、派生链路整体变化,新旧密钥并存一段时间,轮换时间、影响范围全程留痕。
留痕这一段,需要的能力是"SM3 摘要 + SM2 整体签名"。周期台账记录签发数、拒绝数、轮换时间并整体签名,改一个数字即验签失败;四段能力的组合正好覆盖四层面加密钥管理,也直接对应 06 节那几份清单的核查项。
08 | 验收清单与下一步
上线前建议逐项过一遍这张表:
| # | 验收项 | 通过标准 |
|---|---|---|
| 1 | 要求映射表 | 每条要求对应到具体动作与证据 |
| 2 | 登录凭据机制 | 挑战-应答签名,非明文口令比对 |
| 3 | 票据签名字段 | 覆盖主体、受众、签发者、有效期 |
| 4 | 字段完整性 | 改任一字段验签失败 |
| 5 | 受众校验 | 送错系统的票据被拒 |
| 6 | 时效校验 | 过期票据被拒 |
| 7 | 跨系统不可通兑 | 他域公钥验不过本域票据 |
| 8 | 分层派生 | 根—域—用途三层,可复现 |
| 9 | 派生隔离 | 不同业务域派生密钥不同 |
| 10 | 根密钥保护 | 在硬件密码机内、无明文副本 |
| 11 | 轮换周期 | 周期明确、最近一次可查 |
| 12 | 轮换并存期 | 新旧密钥并存、切换无大面积失败 |
| 13 | 周期台账 | 签发数、拒绝数、轮换时间齐备 |
| 14 | 台账完整性 | 改一个数字即验签失败 |
| 15 | 主体标识 | 用持久匿名标识而非可直接识别字段 |
趋势上看,标准这条线的检查重心正在从"系统有没有"走向"条款对不对得上、证据拿不拿得出"。过去只要单点登录能用就算及格;现在评审会随机挑一条要求,要求五分钟内给出对应证据。这个迁移对架构的实质要求是:密钥管理与审计留痕必须前置到设计阶段,而不是上线以后补。
下一篇预告:我们进入第 2 个工作日,看统一身份认证系统技术文档这条线上,技术文档、招标参数与数据加密方案怎么组织成一份能直接用于选型与评审的材料。
09 | 常见问题:统一身份认证系统国家标准的 4 个高频疑问
- Q: 统一身份认证系统国家标准到底是哪一份,要怎么做对标?
- A: 结论是不存在单独一份叫这个名字的国标,要对的是一组要求。网络安全法、数据安全法给义务,GB/T 22239-2019 与 GB/T 39786-2021 给技术与管理要求,密钥管理决定能不能举证。做法是先建一张映射表,把每条要求翻译成具体动作与证据文件。
- Q: 统一身份认证系统实施案例要怎么做参考才不会被带偏?
- A: 结论是看它的定级、系统构成与数据敏感度,而不是看它用了哪些功能。同一套做法在三级系统和二级系统上的举证深度完全不同;照抄功能清单,最常见的结果是条款只对上一半。先确认自己的定级与数据清单,再挑相近的案例参考。
- Q: 统一身份认证系统密钥管理方案里的轮换周期要怎么做才合规?
- A: 结论是轮换周期要写进方案并留记录,常见做法是按季度到按年分层设置:票据密钥周期短、域密钥居中、根密钥最长。关键不是具体多长,而是周期明确、最近一次轮换时间可查、新旧密钥有并存期,切换时不会大面积验签失败。
- Q: 统一身份认证系统密钥管理方案里票据要怎么做才防越权?
- A: 结论是票据必须带受众与有效期,且业务系统做三选三校验。签发时把主体、受众、签发者、有效期一起算摘要再签;校验时先验签、再比对受众是不是自己、最后校验时效,任一条不过即拒绝。
相关阅读
- 智慧校园统一身份认证平台的认证授权链路
- 高校核心系统密评方案的四层面证据链
- 工业互联网等保合规的密码应用框架
文章作者:安当加密-焱垚