第四节 脱敏算法详解:替换、加密、掩码、截断、泛化
做接口脱敏这事,很多人上来就问:“用哪种算法?”说实话,没有万能答案。每种算法都有自己的脾气,用对了场景是利器,用错了就是坑。我翻了这几年项目里的踩坑记录,今天把这五种常用算法掰开揉碎了讲。
一、替换算法
替换说白了就是用预设的固定字符或映射值换掉敏感字段。最常见的做法是把手机号中间四位换成星号,比如 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 + 盐 | 否 | 快 | 密码、登录凭证 |
三、掩码算法
掩码和替换有点像,但掩码通常保留格式特征。比如信用卡号 4111 1111 1111 1111 掩码后变成 4111 **** **** 1111。它既让肉眼看不出完整信息,又保留了位数和部分字符,方便人工校验。
我一般只在展示层用掩码。后端传数据的时候,能传明文就传明文,到了前端再掩码。“前端脱敏”这个思路很多人反对,觉得不安全。但如果是纯展示,且前端不落盘、不转发,我觉得完全可行。你想想看,真要拦截流量,攻击者直接抓包拿明文,掩码根本防不住。掩码的目的是降低“惊鸿一瞥”的信息泄露风险,不是魔法护盾。
// 信用卡掩码:保留前6后4
function maskCard(card) {
return card.replace(/^(\d{6})\d+(?=\d{4})/, '$1****');
}
四、截断算法
截断就是直接切掉一部分。比如把身份证号只保留前6位和后4位,中间全删。极端的时候甚至只保留最后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+';
}
六、算法选择对比
下面这张表帮你快速决策。记住:没有银弹,组合使用才是常态。
| 算法 | 保真度 | 可逆性 | 性能 | 推荐场景 |
|---|---|---|---|---|
| 替换 | 低 | 否 | 极高 | 日志、展示 |
| 加密 | 高 | 是 | 中/低 | 存储、传输 |
| 掩码 | 中 | 否 | 极高 | 前端展示、客服界面 |
| 截断 | 低 | 否 | 极高 | 模糊匹配、低频分析 |
| 泛化 | 中 | 否 | 高 | 数据挖掘、合规交付 |
七、组合策略实战经验
最后说点实在的。我在项目中总结了一条经验法则:按数据生命周期选算法。
- 采集阶段:能用掩码就用掩码,性能第一。
- 存储阶段:必须加密,密钥独立管理。我习惯用 AAD(附加认证数据)配合 AES-GCM,防篡改。
- 处理阶段:如果要跑分析,上泛化或截断;如果要关联其他系统,用哈希保持一致性。
- 销毁阶段:确保加密密钥立即失效,替换数据不必再回写。