在最近的开发日常里,“Vibe Coding” 成了一个非常火的词。借助诸如 Codex、CC、Copilot 这类 AI 编程工具,我们只要有个好主意,几句 Prompt 就能让全栈应用跑起来。开发速度起飞,但问题也随之而来:业务跑得太快,安全往往被甩在后面。
比如,当我们的产品需要处理客户的敏感信息时——让客户绑定他们自己的 OpenAI API Key、存入他们加密货币钱包的私钥,或者保存服务商的 Webhook 凭证,等等。如果在以前,为了快点上线,我们可能会直接把这些敏感数据明文存进关系型数据库。但这就像是在赛博世界里裸奔,一旦数据库泄露、或者是某个内部接口权限配置失误、或者跟心怀不轨的开发者合作……后果不堪设想。
真正的工业级标准是使用物理的 HSM(Hardware Security Module,硬件安全模块)或者像 AWS KMS 这样的云端密钥管理服务。但对于初创团队或个人开发者来说,这些方案要么贵得离谱,要么配置繁琐,极大地破坏了 Vibe Coding 那种顺畅的心流。
为了解决这个痛点,我用 Cloudflare Worker + KV 撸了一个开源项目:meathill/hsm。它是一个轻量级、低成本、免运维,但安全性足以吊打“明文存储”或“单密钥全局加密”的软件定义的密钥管理系统。
那个,它虽然名为 HSM,但其实是个 KMS——因为我也是最近才知道这东西,所以建仓库时误写成 HSM,但是 AI 告诉我这其实是个 KMS……我也懒得改名字了,因为对我们普通开发者来说,其实没啥区别。后面也会混用这两个名词,勿怪勿怪。
接下来跟大家聊聊,我是怎么设计这个系统的,以及为什么 Cloudflare Worker 简直是这类微服务的绝佳载体。
核心设计:不留单点信任的“加密黑盒”
在这个 HSM 的架构设计里,我最关注的一点是:即使黑客拿到了数据库的全部权限,甚至 Cloudflare 后台的只读权限,他也解不开用户的密钥。 听起来有点神奇?其实核心原理并不复杂,主要是组合了三个关键的安全策略:
1. 密钥分片 (Key Splitting) 与运行时合成
系统中没有一个所谓的“万能上帝主密钥”被静态地存在某个地方。解密任何数据,都需要两把“钥匙”的碎片:
-
碎片 A (
CF_SECRET_PART):配置在 Cloudflare Worker 的环境变量里,由服务端持有。 -
碎片 B (
X-HSM-Secret):由调用方掌握,每次请求时通过 HTTP Header 传过来。
当 Worker 收到请求时,会在内存中将 A 和 B 拼接,通过不可逆的 KDF(密钥派生函数)实时计算出真正的主密钥(KEK)。这意味着,如果有人黑进了数据库和环境变量,他没有业务服务的 Header;如果有人截获了内网流量,他没有环境变量。缺乏完整的上下文,数据就是一堆废字符串。
2. 信封加密 (Envelope Encryption)
我们不直接用主密钥加密客户的数据。对于每一条存入的客户密钥,系统都会随机生成一把全新的、独立的数据密钥(DEK,基于 AES-GCM-256)。
- 用这把随机的 DEK 去加密客户的明文密钥。
- 然后再用刚刚合成的主密钥(KEK)去加密这把 DEK。
- 最后把它们打包存入数据库。
这样一来,每一条数据的加密“指纹”都是独一无二的,极大地限制了单次暴力破解的收益。
3. 防枚举的存储混淆
存进 KV 数据库时,Key 的名字绝对不能是 user_1001_api_key 这种明文。我们使用 HMAC 算法,加上一个单独的盐值,把存储路径做一次不可逆的哈希。黑客就算拉库走人,面对一堆乱码的 Key 和乱码的 Value,根本无法把数据和特定的受害者对应起来。
为什么是 Cloudflare Workers?聊聊 Service Binding 的魔法
如果你要部署这样一个高安全要求的内部微服务,通常你需要配置复杂的 VPC 内网规则、互相签发 JWT Token 来验证身份,这对于前端/全栈工程师来说相当折磨。
而 Cloudflare Worker 提供了一个神级特性:Service Binding(服务绑定)。
顾名思义,Service Binding 允许我们的不同 Worker 之间直接进行通信,完全不经过公共互联网。
假设我们的主业务是一个 Next.js 或 Nuxt 应用(通过 OpenNext 跑在 Cloudflare 上),当我们的主业务需要存取密钥时,不需要发起公网 HTTP 请求,只需要在代码里这样调用:
// 主业务 Worker 内部的代码
const response = await env.HSM_SERVICE.fetch(
new Request('<https://hsm/keys/my-app/user-1/token>', {
headers: { 'X-HSM-Secret': 'my-super-secret-client-key' }
})
);
这个特性的杀手锏在于:它天生就是安全的,可以直接省去后端的权限校验开发!
因为 HSM_SERVICE 只能在 Cloudflare 的控制台或 wrangler.toml 里由管理员显式绑定。HSM Worker 甚至可以完全拒绝所有来自公网的请求,只响应来自 Service Binding 的内部调用。这实现了真正的“零信任(Zero Trust)”架构,把网络层攻击的概率降到了最低。
开放 API 的想象力:让用户放心交出敏感数据
除了作为公司的内部服务,这个架构也完全可以作为 Open API 对外提供。
想象一下你正在做一个类似 Zapier 的自动化工具,需要用户填入他们的各类平台账号密码。如果你向用户声明:“你们的凭证是通过端到端的加密存储的,在加密过程中,甚至我们作为平台方也无法单独解密你的数据”(你可以让用户在客户端侧生成一个随机串作为“碎片 A”并保存在他们的浏览器本地或密码管理器中)。
这会极大地增加产品的信任感。即使我们的服务器被一锅端,由于黑客拿不到存放在用户设备上的那个碎片密钥,用户在我们平台留下的敏感信息依然是绝对安全的。
不想自己部署?试试我们的线上服务
如果你只是想快速体验一下,或者懒得独立部署一套 KMS,我也提供了一个现成的线上服务:hsm.meathill.com。
开箱即用,无需注册,直接通过 HTTP API 进行密钥的存取操作。而且我们已经全面支持 CORS,所以即使是纯前端项目,也可以直接在浏览器里调用,不需要额外搭后端做中转。
写入密钥:
const res = await fetch('<https://hsm.meathill.com/keys/my-app/user-1/token>', {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'X-HSM-Secret': 'my-super-secret-client-key',
},
body: JSON.stringify({ value: 'the-data-i-want-to-protect' }),
});
if (res.ok) {
console.log('数据安全入库!');
}
读取密钥:
const res = await fetch('<https://hsm.meathill.com/keys/my-app/user-1/token>', {
headers: {
'X-HSM-Secret': 'my-super-secret-client-key',
},
});
const result = await res.json();
if (result.success) {
console.log('取得解密后的数据:', result.data.value);
}
就是这么简单。/keys/:path 是一个 RESTful 风格的接口,路径可以自由组织(比如 my-app/user-1/token),写入用 PUT,读取用 GET,删除用 DELETE。你可以把它当成一个安全的、加密的 KV 存储来用——写入时加密,读取时解密,中间的一切都由服务自动处理。
结语
在 Vibe Coding 的浪潮下,我们比以往任何时候都需要像 meathill/hsm 这种“开箱即用、默认安全”的基础设施。它可能只用了几百行代码,但足以帮你在狂奔的业务中守住数据安全的底线。
项目目前已经开源在 GitHub:**https://github.com/meathill/hsm**
开箱即用的免费在线服务:https://hsm.meathill.com
如果你觉得这个思路对我们的项目有帮助,欢迎去点个 Star,提个 Issue,或者直接 Fork 下来改造成最适合我们的形态。我们一起把安全这件事,做得像 Vibe Coding 一样简单自然。
常见问题解答 (FAQ)
1. 这个项目能完全替代硬件 HSM (Hardware Security Module) 吗?
不能。 物理 HSM 的核心是“密钥绝不离开安全芯片”,加解密都在物理黑盒内完成。而基于 Cloudflare Worker 的方案,在进行解密运算的那几毫秒内,明文密钥依然会存在于 Worker 的运行内存中。但对于绝大多数初创公司、内部系统或非国家级金融项目来说,这种“软件定义的 KMS”在安全性、性能和成本上已经达到了完美的平衡。
2. 如果 Cloudflare KV 数据库的数据丢了怎么办?
KV 负责的是持久化存储,强烈建议你定期通过脚本将 KV 里的全量密文数据备份到其他云存储(如 AWS S3 或 R2)。因为数据是加密的,备份操作本身非常安全,不用担心备份文件泄露导致安全事故。
3. 如果我丢失了配置在环境变量里的密钥碎片 (Env Secret) 怎么办?
那我们的数据就真的永远拿不出来了。 由于采用了强加密算法,没有正确的 Env Secret 就无法还原主密钥 KEK。所以,在系统初始化后,请务必将这部分环境变量妥善保存在 1Password 等离线/高安全级别的密码管理器中。
4. 加解密操作全在边缘节点跑,性能和延迟怎么样?
这正是选择 Cloudflare 的优势。Worker 运行在距离用户极近的边缘节点,不仅冷启动时间几乎为零,而且 AES-GCM 和 HMAC 这类 Web Crypto API 操作都有底层优化。相较于跨可用区去调用传统的云数据库,这套方案在延迟上的表现非常出色。
5. 这个系统支持密钥轮换 (Key Rotation) 吗?
目前架构设计上,由于使用了信封加密,数据密钥(DEK)每次存入都是全新的。如果你需要轮换主密钥(KEK),可以通过发布新版本的方式,引入版本号(Version)字段进行平滑过渡。
转载自 我的博客,两边同步更新,欢迎留言讨论



8

