第四节 脱敏算法详解:替换、加密、掩码、截断、泛化

做接口脱敏这事,很多人上来就问:“用哪种算法?”说实话,没有万能答案。每种算法都有自己的脾气,用对了场景是利器,用错了就是坑。我翻了这几年项目里的踩坑记录,今天把这五种常用算法掰开揉碎了讲。

一、替换算法

替换说白了就是用预设的固定字符或映射值换掉敏感字段。最常见的做法是把手机号中间四位换成星号,比如 138****1234。实现简单,性能也好。

适用场景:日志脱敏、前端展示、测试数据。

不过要注意,替换是不可逆的。一旦替换,原始信息就丢了。我记得有个项目,测试环境用替换算法处理了身份证号,结果联调时发现用脱敏后的数据怎么都查不到真实用户,排查半天才发现是替换策略定得太死。

// 替换示例 —— 手机号中间四位变 *
function maskPhone(phone) {
  return phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2');
}

二、加密算法

加密保留了恢复能力,适合需要反向解析的场景,比如银行交易流水。但加密会带来性能开销,密钥管理也挺头疼。我习惯把加密分成两类:对称加密(AES)和哈希加盐(不可逆)。

举个例子,用户密码必须用哈希加盐,绝不能直接用 AES 再存回数据库。为什么?一旦密钥泄露,所有密码全裸奔。之前有个金融项目,他们用 AES 加密了身份证号存进数据库,我当场就给拦下来了——你想想看,DBA 拿着密钥不就等于拿到了所有身份证?后来改成了分段设计:身份证号用 AES 加密,但数据库里只存密文,密钥由另一个安全模块托管。

算法可逆性性能典型用途
AES是中等姓名、地址、证件号
RSA是慢密钥交换、小字段加密
SHA-256 + 盐否快密码、登录凭证
避坑指南:我曾经在日志场景里用过 RSA 加密用户邮箱,结果日志量一上来,CPU 直接飙到 90%,生产事故。后来全换成了掩码,几毫秒搞定。

三、掩码算法

掩码和替换有点像,但掩码通常保留格式特征。比如信用卡号 4111 1111 1111 1111 掩码后变成 4111 **** **** 1111。它既让肉眼看不出完整信息,又保留了位数和部分字符,方便人工校验。

我一般只在展示层用掩码。后端传数据的时候,能传明文就传明文,到了前端再掩码。“前端脱敏”这个思路很多人反对,觉得不安全。但如果是纯展示,且前端不落盘、不转发,我觉得完全可行。你想想看,真要拦截流量,攻击者直接抓包拿明文,掩码根本防不住。掩码的目的是降低“惊鸿一瞥”的信息泄露风险,不是魔法护盾。

// 信用卡掩码:保留前6后4
function maskCard(card) {
  return card.replace(/^(\d{6})\d+(?=\d{4})/, '$1****');
}

四、截断算法

截断就是直接切掉一部分。比如把身份证号只保留前6位和后4位,中间全删。极端的时候甚至只保留最后4位。截断的优点是数据量小、处理极快,但信息损失也最大。很多场景下,截断后的数据已经没法做关联分析了。

我记得有一次做用户画像数据脱敏,业务方非要保留年龄和地区分析能力,但安全要求身份证号必须脱敏。我们用了截断 + 区间泛化(后边会讲),保留了年份和省份代码,丢弃了具体的月和日。既满足了业务,又迈过了合规红线。

关键指标:截断后保留的位数,必须根据业务最小需求 + 安全冗余来定。通常保留3-4位有效信息已经足够模糊。

五、泛化算法

泛化是把精确值模糊成范围或类别。比如把具体年龄 28 岁变成“25-30岁”,把精确地址“北京市海淀区中关村大街1号”变成“北京市海淀区”。泛化的好处是保留统计特性,适合数据分析、风控模型训练。

但泛化的粒度很难把握。泛化太粗,业务价值丢失;泛化太细,安全保护不足。我习惯用 k-匿名 原则来校准:确保每组泛化后的数据至少有 k 条记录不可区分。以前处理医疗数据时,我们把出生年月泛化到年份,把邮编泛化到前三位,同时附加了噪声扰动,才敢放给外部合作方。

// 年龄泛化示例
function generalizeAge(age) {
  if (age < 18) return '0-17';
  if (age < 25) return '18-24';
  if (age < 35) return '25-34';
  if (age < 45) return '35-44';
  return '45+';
}

六、算法选择对比

下面这张表帮你快速决策。记住:没有银弹,组合使用才是常态。

算法保真度可逆性性能推荐场景
替换低否极高日志、展示
加密高是中/低存储、传输
掩码中否极高前端展示、客服界面
截断低否极高模糊匹配、低频分析
泛化中否高数据挖掘、合规交付
脱敏算法分类与选型框架 脱敏算法选型决策树 敏感数据 不可逆(放弃恢复) 可逆(需要还原) 替换 掩码 截断 泛化 AES 对称 RSA 非对称 其他 FPE 组合使用:如“AES加密 + 掩码展示” 或 “截断 + 泛化” 先根据是否可逆分叉,再按具体场景选叶子节点

七、组合策略实战经验

最后说点实在的。我在项目中总结了一条经验法则:按数据生命周期选算法。

  • 采集阶段:能用掩码就用掩码,性能第一。
  • 存储阶段:必须加密,密钥独立管理。我习惯用 AAD(附加认证数据)配合 AES-GCM,防篡改。
  • 处理阶段:如果要跑分析,上泛化或截断;如果要关联其他系统,用哈希保持一致性。
  • 销毁阶段:确保加密密钥立即失效,替换数据不必再回写。
再啰嗦一句:千万不要把所有字段用同一种脱敏算法。手机号和身份证号的安全风险不同,算法强度也该不同。我曾经接手过一个全用掩码的项目,所有字段都保留前6后4,结果发现地址字段只泄露了“北京市海淀区”其实没关系,但银行卡号前6后4再结合外部信息就够做信用卡欺诈了。所以,按字段风险等级分级脱敏,这是我给你的最高优先级建议。