Files
blog/content/posts/e2e-false-need.md

5.8 KiB
Raw Permalink Blame History

title, description, date, draft, tags
title description date draft tags
E2E 是个伪需求 配置中心的端到端加密方案,上午落地,下午死在了自己的安全评估里。不问威胁模型就堆加密原语,堆得越专业越危险。 2026-08-24T20:25:00+08:00 false
架构
安全
配置中心

背景

项目里散落着六处配置:客户端直连的对象存储密钥、推送 Token、第三方 API Key……全部硬编码在客户端代码里。今天要把它们收进统一配置中心,核心诉求一句话:

这些核心配置不能被泄露,不能在被人逆向时直接拿到。

围绕这句话,方案迭代了三轮,最终回到了一个最初根本没考虑过的答案。

方案 C:看起来很专业

上午拍板的是一套「按凭据类型区分加密」的设计:

凭据类型 前缀 存储 服务端回显
纯客户端凭据 cred_ 客户端公钥混合加密RSA-OAEP + AES 服务端无私钥,不可见
服务端可管理 scred_ 对称加密 可回显编辑

听起来很美:客户端上传公钥,配置中心用公钥加密,数据库里全是密文,连服务端管理员都看不到明文--教科书级的端到端加密(E2E)。落地、验证、全绿。

下午做安全评估的时候,它塌了。

评估:三个致命缺陷

1. 公钥踩踏

一份配置要下发给多个客户端,加密时用谁的公钥?A 的公钥加密,B 就解不开;给每人存一份密文,配置更新就要全量重加密。E2E 假设「一对一私聊」,而配置中心是「一对多广播」--场景就不匹配。

2. 公钥冒领

公钥是公开的。任何人都能拿到公钥,加密一份假凭据提交上来,服务端无私钥无法验证内容真伪,只会原样存储、原样下发。你防住了自己人看,没防住别人写。

3. 两端都有明文,E2E 防的是谁?

这是最根本的一问。E2E 的威胁模型是「服务端不可信」(即时通讯怕服务器运营商偷看)。可我们的场景:

  • 客户端拿到配置后本来就要在内存里解密成明文来用
  • 服务端是自己写的、自己部署的,本来就在信任边界内

真正想防的「逆向」发生在客户端,而 E2E 加密的是客户端到服务端这一段。 加密原语堆得再高级,防的都不是你要防的那个人。

点破:物理冲突与真正的命门

继续往下问,会碰到一个无解的矛盾:

「客户端要用凭据」和「客户端逆向拿不到凭据」,物理冲突。

客户端要用,就必须持有明文(至少在内存里);能防的边界只有反编译静态分析(99% 的场景),动态调试 dump 内存防不了--这条要诚实承认,任何声称「客户端防动态逆向」的方案都是自欺。

再回头看真正的命门:就算凭据全部移到服务端,客户端代码里还硬编码着一个静态 API Key。逆向者拿到这个 Key,照样能调用接口把全部凭据拉走。前面所有加密等于白忙。

结论浮出水面:这个场景的安全关键根本不在加密,在鉴权。

最终方案:最简三步

推翻方案 C 之后,剩下的东西少得可怜:

  1. 删掉整个 E2E:公钥上传、混合加密、双前缀,全删
  2. 存储对称加密 + 后台脱敏:数据库泄露不泄明文,界面回显一律 ****--这一步防的是「数据库被拖」
  3. 鉴权换动态登录:工号 + 密码换短期 JWT,凭据经 TLS 下发、内存用完即弃、不落盘--这一步防的是「逆向拿到静态钥匙拉走全部」

删掉的代码比新写的还多。验证清单反而更短更硬:有 JWT 才能拿配置(无 token 401)、错误密码拒绝、存储确认为密文。

同一天的另外三次「推翻」

今天的主题像是「推翻自己」,不止这一次:

二维码 404 双层修复。弹窗打不开,第一层根因是 Bootstrap 5 移除了 jQuery 插件集成,八处旧写法全部改原生 API。改完发现页面还是坏的--真正的 404 在用户实际访问的公网入口:那边只反代了 PHP 请求,静态资源落在本地目录全是 404。教训:只测内网等于没测,验证必须覆盖用户真实入口。

下载量统计全 0。不是统计代码有 bug,是客户端走渠道轮转直连渠道下载,根本没经过服务端,自然不计数。修复不是改计数逻辑,而是补一个「下载完成才上报」的端点,顺手用 MD5 投票机制(三票阈值、三天窗口、投票人去重)让多个客户端互相校验文件哈希。

32 条 FAIL 日志。扫描出 32 条失败记录,逐条分类后:31 条是设计内的拦截(二选一城市待确认、多候选客户待澄清、在保不派单……),只有 1 条是真 bug--无操作人参数时误报「凭证过期」,实际该报「写操作必须指定操作人」。红色不等于故障,先分类再动手

总结

四件事,四个同款教训:

  1. 先问威胁模型,再选加密方案。E2E 防「服务端不可信」,数据库加密防「拖库」,动态鉴权防「逆向拉取」--三个威胁,三套解法,混着用只会互相拖累。
  2. 鉴权优先于加密。加密保护数据形态,鉴权决定数据归属。静态钥匙在手里,保险柜再厚也是空的。
  3. 验证要覆盖真实入口。内网全绿的系统,公网入口可能全是 404。
  4. 最简方案往往更安全。攻击面小、可审计、能讲清楚。复杂度本身也是一种漏洞。

方案 C 不是死于实现太糙,是死于问错了问题。安全设计的第一步不是选算法,是画威胁模型--搞清楚你到底在防谁。


本文已脱敏,不含真实域名、IP、密钥或用户数据。