☰
政务身份认证隐私保护:数据分级、不可逆存储与脱敏窗口
2026/10/31 9:23:14 网站建设 项目流程

简介:《C0131国家政务服务平台统一身份认证隐私保护要求》是一份面向政务服务平台统一身份认证国家节点、地方和部门节点的标准规范PDF,适合系统建设、运维、合规与个人信息保护岗位查阅。它围绕隐私数据定级、判定、使用与责任展开,明确一级至三级数据的保护尺度,并细化收集、保存、使用、加工、共享披露、导出输出、归档销毁等环节的操作边界,附录A还给出自然人身份信息隐私判定说明。资源包共1个PDF文件,约188KB,篇幅精炼便于检索条款,已有820人学习。读者可据此梳理统一身份认证场景下的数据分级清单、最小必要与知情同意要求、共享审批和销毁流程,也能为隐私保护制度编制、检查检测和责任划分提供可引用的标准依据。

1. 三级分级不是敏感度排序,而是可逆性约束

政务服务平台统一身份认证隐私保护这份规范里最反直觉的一条,是对三级数据的存储要求:在互联网区,它必须以不可逆方式存储,不许明文、不许可逆加密。换句话说,一份证件编号一旦按这个要求落库,从存储介质上就再也还原不出明文,连系统自己都拿不回来。多数人对隐私保护的直觉是"把锁加得更结实",而这份 2018 年定稿的规范给出的答案是——有些数据压根不该以能还原的形态存在。搞懂这条,后面所有的定级规则、脱敏比例、明文驻留窗口为什么长成那个样子,就都有了解释。

2. 定级模型:为什么"证件类型"是一级,"证件编号"是三级

2.1 定级标准不是敏不敏感,而是能不能回到具体的人

先把三个定义并排放一遍。一级数据是"不能对应到自然人实体身份信息的数据";二级是"可用于标识自然人实体的身份信息,且较公开的数据";三级是"可用于标识自然人实体的身份信息,且具有较高隐私性的数据"。三段定义里反复出现的是同一个短语——"对应到自然人实体"。所以这个级别衡量的不是"这条信息泄露了有多尴尬",而是"拿到这条信息,离知道这是谁还有多远"。

把附录 A 那张表摊开看,这条逻辑就非常清楚。证件类型是一级——身份证、护照、社保卡,知道自己属于哪一类证件,说明不了任何具体的人。实名等级、实名核验日期、性别、民族、国籍、用户类型,全部是一级,原因相同:这些字段描述的是"某一类人",不是"某一个人"。它们的作用是描述属性,不是定位个体。

真正有意思的是"证件散列码"被定为一级。散列值当然是唯一的,一个散列值只对应一个人,从唯一性上讲它比姓名还强。但它的唯一性是"盲"的:单独拿着一个散列值,没有任何办法回到明文。标准把"可对应"理解成"在系统内可以直接读出身份",而不是"数学上存在唯一映射"。这个区分是整个分级模型的支点,也是后面统一散列函数那套设计能立得住的前提。

再看三级:证件编号、社保卡号、户籍地址、居住地址。这四样有个共同点——它们本身就是答案,不是线索。不需要再查任何东西,看一眼证件编号就知道这是谁。这类数据一旦泄露,受害者连"要不要澄清"的余地都没有,因为信息是完整且确定的。

二级夹在中间:姓名、登录账号、手机号、邮箱、生日、学历、工作单位、支付宝号、微信号、发卡地、证件有效期与失效期、注册时间、第二和第三手机号。这些是"线索",单条拿出去的指向性有限,但组合起来(姓名+手机号+工作单位)就能相当准确地锁定一个人。规范把它们判为二级而不是三级,本质上是在赌一个概率:单字段泄露的伤害可控,多字段联合泄露才致命,所以防护重心放在"禁止关联"而不是"禁止存储"上。

2.2 附录 A 其实是一张身份可还原度映射表

把附录 A 的完整字段按级别归类,结构一目了然:

级别字段共同特征
一级证件类型、证件散列码、实名等级、实名核验日期、性别、民族、国籍、用户类型描述类别或不可逆,无法回到个体
二级姓名、登录账号、手机号、第二手机号、第三手机号、邮箱、生日、注册时间、学历、工作单位、发卡地、证件有效日期、证件失效日期、支付宝号、微信号可指向个体,但公开度较高或需组合
三级证件编号、社保卡号、户籍地址、居住地址本身即身份答案,隐私性高

这张表最值得琢磨的地方,是它把"生日"放在二级、"证件编号"放在三级。很多人第一反应会觉得生日更敏感,因为生日常被用作找回密码的验证问题。但从"能不能回到具体的人"这个尺度看,同一天出生的人有几十万,生日只是缩小范围,证件编号才是唯一定位。这也解释了为什么规范在脱敏规则里对证件编号要求"只显示后四位",而对生日没有单独列出更严格的处理——风险量级本来就不同。

同样的思路可以解释"工作单位"是二级、"户籍地址"是三级。工作单位是"某公司员工"这种粗粒度归属,地址是"住在哪一格"这种精确定位。前者泄露的最坏结果是骚扰电话变多,后者泄露的最坏结果是人身安全。

提示:这张表是规范性附录,不是参考示例。落库设计时字段级别要照抄,不能按"我们业务觉得不敏感"自行下调。

2.3 儿童提升与生物特征的二分法

规范在判定章节留了两个补丁。第一个补丁针对未满 14 岁的儿童:可以提升数据隐私级别。这条不是可选项的技术细节,背后是同意能力的判断——儿童不具备完整的民事行为能力,其监护人代行的同意在风险上要打折,所以同样的数据落在儿童身上要按更高一级对待。工程上的实现通常是在用户模型里加一个年龄段标记,在定级函数入口先做一次级别上调,再走常规判定。

第二个补丁针对生物特征,而且做了个很讲究的二分:人脸、声纹这类"较为公开的生物特征数据"属于二级;指纹这类"作为可认定个人信息的生物特征数据"属于三级。为什么不统一按最高级处理?因为获取门槛不同。人脸和声纹在公开场合天然暴露,采集成本极低,它作为"秘密"的价值本来就有限;指纹是你不主动交出来、别人基本拿不到的东西,一旦泄露,它作为身份凭证的确定性极高,而且换不了——密码泄露可以改,指纹泄露没法改。

还有一类容易漏判:访问记录。个人在统一身份认证体系中的登录记录、政务门户访问记录,明确属于二级。这一条在落地时经常被当成"日志"而不是"隐私数据",随手打到日志平台里明文存着,一存就是好几年,这恰恰是最典型的翻车现场之一。

3. 存储层:为什么三级数据在互联网区必须不可逆,在外网却允许可逆

3.1 用户标识:散列值成了系统的唯一索引

规范对用户标识的定义是:用户个人信息中的证件号码等唯一识别码形成的散列值,在统一身份认证系统中唯一。这句话信息量很大。它意味着整个体系的跨节点识别不靠明文证件号,而靠一个散列值。国家节点和地方、部门节点之间传的是这个散列值,查的也是这个散列值。

这就带来一个关键设计要求:散列函数必须是统一的。如果每个节点自己加盐、自己选算法,同一个自然人在不同节点算出来的散列值就不一样,跨节点查询直接失效。规范里那句"不可逆加密方法应采用国家节点统一提供的散列函数对明文进行散列运算",说的就是这件事。

常见的实现思路大致是这样:

# 用户标识生成:全局统一散列,盐由国家节点统一下发 import hashlib def build_user_id(id_number: str, global_salt: bytes) -> str: # id_number 为证件编号明文,仅在内存中短暂存在 # global_salt 由国家节点统一分发,各节点不得自行更换 raw = id_number.encode("utf-8") + global_salt # 使用国家节点指定的散列算法,保证跨节点结果一致 return hashlib.sha256(raw).hexdigest() def persist_user(user_id: str, id_number: str): # 三级数据在互联网区只落散列值,明文不落库 db.execute( "INSERT INTO user_identity(user_id, id_hash) VALUES (?, ?)", (user_id, user_id), # id_hash 即散列值本身 ) # 明文用完立即从内存清除,不进入任何缓存 del id_number

这段代码的关键不在哈希本身,而在两个约束:一是盐必须全局唯一,否则跨节点比对失效;二是明文不落库、不进缓存,函数返回后立即销毁。参数上唯一能变的是散列算法,但算法一改,历史数据全部作废,所以实践中算法也被锁死,不轻易升级。

这里有个必须点破的张力。统一散列让"同一个人在不同节点能不能被认出来"变成了可能,这本身是一种可关联性。而规范第 6.5 条又明确禁止用两个或两个以上用户的个人信息做关联分析,包括用散列值分析。技术给出了能力,制度关掉了开关——这是整份规范里最典型的一处"能力与授权分离"的设计。理解这一点,才能明白为什么后面会有那么重的日志和审计要求。

3.2 密钥托管:为什么管密钥的人不许碰数据

规范对密钥的要求写得很硬:密钥必须存放于符合 GM/T 0051-2016 的系统或设备中,由专人管理,密钥管理人员不得从事数据操作、加工、使用等工作,且必须是本节点正式工作人员,不得来自软件开发商、服务商等第三方机构。

这几句话合起来是一条职责分离原则。常见的泄露路径不是外部攻击,而是"能加密的人顺便也能看数据"。如果运维外包人员既持有密钥又能连数据库,那加密在事实上等于没加——他可以在应用层之外直接把数据解出来。规范把"持有密钥"和"操作数据"拆给两拨人,任何单点都无法独立完成解密,这才是加密真正生效的前提。

注意:这条在验收时经常被忽略。检查时不要只看"有没有加密",要问一句"谁能同时拿到密钥和库连接",答案必须是没有人。

3.3 两种密码算法的分工

规范点名了 SM2 和 SM4。这两个算法在体系里承担的是不同角色:SM4 是分组密码,速度快,适合加密数据本体;SM2 是椭圆曲线公钥算法,适合做密钥交换和签名。常见的实现思路是信封加密——用 SM2 加密一把临时的 SM4 会话密钥,再用这把 SM4 密钥加密实际数据,解密时反过来。这样既避免了对称密钥的分发难题,又不用承受公钥算法加密大数据的性能代价。

真正决定安全边界的不是算法选型,而是前面 3.1 说的那条:三级数据在互联网区走的是不可逆散列,压根没有解密路径;只有电子政务外网这个受控环境里,三级数据才允许以可逆加密方式存储。同一份数据,两个网络区域两套存储策略,这个差异是整份规范里最容易被实现者搞混的地方。

4. 使用层:脱敏比例、二次认证与明文驻留的时间窗

4.1 脱敏显示不是"打个星号",是有下限的

规范对显示的要求分两档。第一档是允许全文显示的场景,只有两个:用户注册时自己填写的内容;用户查看和修改自己的信息时,必须在二次认证之后。二次认证的级别不低于手机短信验证码的双因子,修改信息宜使用实名等级四级(实人认证)。

第二档是默认状态:二级以上隐私数据一律脱敏,除手机号外,脱敏范围不少于 50%。这个"不少于 50%"是个硬下限,很多实现只遮一两位,表面上做了脱敏,实际上一眼就能猜出来,等于没做。

各类字段的脱敏示例在规范里给得很具体:姓名显示最后 1 到 2 个汉字;证件编号和社保卡号只显示最后四位;手机号显示前 3 位和后 4 位;证件有效日期和失效日期只显示后 4 位;邮箱显示 @ 及之后的部分;支付宝号和微信号显示后 4 位;地址类字段长度大于 12 时只显示前 6 位,不足 12 位时隐藏不超过 50%。

手机号被单独豁免 50% 下限,采用固定的"前 3 后 4",原因是它同时承担着二次认证通道的角色,用户需要能核对是不是自己的号。这是一个很现实的取舍:可用性和隐私在这里直接对撞,规范选了可用性,但只给手机号开了这一个口子。

实现上,脱敏应该做成数据出口的统一拦截,而不是散落在业务代码里:

# 脱敏统一在序列化出口执行,业务层拿不到明文拼装机会 def mask(field: str, value: str) -> str: if field in ("id_number", "social_card"): return "*" * (len(value) - 4) + value[-4:] # 证件类:仅留后四位 if field == "mobile": return value[:3] + "****" + value[-4:] # 手机号:前3后4 if field == "name": return "*" * (len(value) - 2) + value[-2:] # 姓名:留最后1-2字 if field == "email": return "*" * value.index("@") + value[value.index("@"):] # 邮箱:留域名 if field in ("address", "work_unit"): if len(value) > 12: return value[:6] + "*" * (len(value) - 6) # 长地址:留前6位 return value[: len(value) // 2] + "*" * (len(value) - len(value) // 2) return value

这段函数的重点是"按字段名分派",而不是按页面分派。按页面写脱敏的后果是:新增一个导出功能、一个消息推送模板、一个对账接口,就很容易绕过脱敏直接吐明文。按字段名分派、放在序列化层,才能保证所有出口走同一套规则。

4.2 三个明文窗口:1000 条 / 24 小时、8 小时、2 小时

规范允许互联网区临时存在未加密数据,但每一处都给了"数量 + 时间"的双重约束:

场景数量上限时间上限销毁要求
实名核验一次一条核验完成即止核验后立即销毁临时数据
注册信息上报本地互联网区不超过 1000 条不超过 24 小时上报完成后销毁明文
国家节点接收上报同上收到后不超过 8 小时处理完成后销毁
用户信息查询接口一次一条发起节点 2 小时内处理完处理完销毁互联网区明文

为什么非要两个约束一起上?因为单独任何一个都能被绕过。只限时间不限数量,24 小时里可以灌十万条进去;只限数量不限时间,每天 1000 条慢慢攒,一年就是三十六万条。真实暴露面约等于数量的上限乘以时间的上限,两个维度同时收紧,才能把窗口压到一个可审计的量级。

这也解释了为什么上报环节要"以明文数据上报全量数据"。加密上报听起来更安全,但实际上会让国家节点无法在校验环节发现数据质量问题,反而催生"先解密到临时库再校验"的更长驻留。规范选择了短窗口 + 明文 + 强制销毁,把风险集中在一个明确可控的时间段里,而不是分散在一条看不见的解密链路上。

4.3 为什么查询接口一次只准返回一条

规范里有一句容易被当成废话的要求:查询接口只允许接收和输出一个用户的个人信息,不得存在一次查询多个用户的服务。这句话的实际含义是——把批量能力从接口层面彻底删掉。

批量接口的危险不在于它本身被滥用,而在于它把"拖库"变成了一次调用。有了批量接口,攻击者只需要一个有效凭证就能拿走十万条;只有单条接口,同样的量需要十万次调用,每一次都会在日志里留下一条记录,异常检测有充足的信号。规范后面要求各环节日志保存不少于一年,正是为了让这些单条调用留下的痕迹能被回溯。

配套的还有导出管理:各节点要制定导出制度,明确少量导出、批量导出、大批量导出的定级定义和管理流程,导出记录至少保存一年,记录内容要包括用途、时间、操作地点、人员、授权信息、文件大小、数据数量,以及所有涉及个人信息的散列值标识。把"谁在什么时候导了多少条、导的是哪几个人"记全,事后才追得回来。

5. 避坑排查:五条最容易翻车的落地细节

5.1 脱敏做了,但导出报表里全是明文

现象:前端页面上显示的是"***4432",用户投诉说后台导出的 Excel 里证件号是完整的。

原因:脱敏做在了 Controller 的返回包装里,导出走的是另一条独立的流式写出链路,压根没经过那层包装。凡是"按接口写脱敏"的实现,新增一个出口就漏一次。

解决:把脱敏下沉到数据序列化层,按字段元数据驱动,任何出口只要序列化就必须过一遍。上线前拿一份字段清单逐项核对每个出口,导出、推送、对账、日志四条链路都要覆盖。

5.2 跨节点查同一个用户,散列值对不上

现象:用户在 A 节点注册,到 B 节点办事时系统提示"查无此人",但人确实是同一个人。

原因:两个节点各自实现了散列逻辑,盐不一样,或者一边用了 SHA-256、另一边用了 MD5。散列值一旦不一致,跨节点识别直接断裂。

解决:散列函数和盐都由国家节点统一下发,各节点只允许调用统一实现,不允许本地重写。已上线系统做迁移时,要在低峰期按用户标识重建索引,重建过程本身也要纳入审计。

5.3 审计日志成了新的泄露源

现象:数据表里干干净净全是散列值,结果日志平台里能搜到完整证件号和手机号明文,而且按规范要保存一年。

原因:为了排查方便,在接口入口把整个请求体打进日志。日志平台的访问控制往往比业务库松得多,等于给隐私数据开了个后门。

解决:日志只记用户标识散列值和操作元数据(操作人、时间、动作、结果),不记业务字段原文。这条要写进日志组件的默认行为里,而不是靠开发自觉。

5.4 删除接口返回成功,但磁盘上还能恢复

现象:用户注销后查询接口确实查不到了,但做介质取证时还能从磁盘扇区里捞出来。

原因:做的是逻辑删除或者只删了索引,数据块还在;或者删了主表,临时表、缓存、预写日志里的副本没动。

解决:销毁必须采用不可恢复方式,并且要覆盖内存残留、缓存、临时文件和临时库表。验收时不要只看接口返回,要看落盘路径上还有没有副本。

5.5 密钥管理员是外包运维,出事查不到责任人

现象:加密配置看着都对,但实际运行时任何有库权限的人都能解出明文。

原因:密钥和数据库连接掌握在同一批人手里,违反职责分离。这种情况在赶工期时特别常见,因为让一个人全干完最省事。

解决:密钥管理员必须是本节点正式工作人员,不得来自开发商或服务商,且不得从事数据操作、加工、使用。这条在合同阶段就要写进条款,不能等到验收再补。

6. 设计取舍:时间窗和数量窗,为什么比"加密传输"更难糊弄

把这份规范从头到尾串一遍,会发现它真正在做的事情不是"把数据锁死",而是"让明文在空间、时间、数量三个维度上同时受限"。这三个维度互相咬合:空间上,三级数据在互联网区只留不可逆散列,物理上就没有明文;时间上,确需明文时给出 24 小时、8 小时、2 小时的硬窗口;数量上,一次一条、一千条封顶。任何单点失守,另外两个维度还能把损失限制住。

对比一下更常见的做法——只做传输加密。链路加密防的是中间人窃听,它对"数据落地之后被谁看了、导出了多少、存了多久"完全没有约束力。而现实中绝大多数隐私事故不是链路被攻破,是内部人员批量导出、临时表忘记清理、日志明文留存。规范把重心放在后一类风险上,这是它和通用安全规范最大的分野。

统一散列这个设计尤其值得单独想一想。它造出了一个全局唯一的用户标识,让跨节点识别成为可能,代价是这个标识本身具备了可关联性。规范的处理方式是:技术上保留能力,制度上关闭用途——禁止用两个及以上用户的个人信息做关联分析,包括用散列值分析,再用不少于一年的日志把这个禁令变成可核查的事实。这是典型的"能力与授权分离",也是这类跨机构体系里唯一可行的路径,因为完全不可关联的系统根本没法互联互通。

如果要验证一个实现是不是真的落到了位,我一般会挑三件事抽查:随便取一个用户,看他在两个节点的散列值是否完全一致;在日志平台搜一遍完整证件号,看能不能搜出来;找一次导出记录,看能不能还原出用途、时间、操作人、授权信息和涉及的个人标识。这三条都过了,基本盘就稳了。

早些年参与一个模拟项目的身份模块评审,我们当时把力气全花在加密算法选型和传输链路上,自测报告写得漂漂亮亮。结果对方只问了一句"导出报表走的是哪条链路",我们才发现导出模块为了性能绕过了脱敏层,全量明文直出。从那以后我每次设计身份相关字段,都会先在纸上把"这条数据泄露后能还原到谁"写一遍,再决定它落哪一级、走哪个出口、留多久。这份规范值得放在手边,尤其在你要动用户模型字段的时候,翻到附录 A 对一遍,比事后写事故报告省事得多。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询