Payload 签名
FortressFlag 发给你任何一个应用的每一个负载(payload)都带着签名,而每个 SDK 都会在任何一个 flag 值改变之前检查它。你什么都不用做就能得到这一点——SDK 内置了生产公钥,并且默认就会验证。这一页解释这能给你带来什么、两个策略设置各是什么意思,以及你的应用今天信任哪些密钥。
签的是什么,为什么要签
Section titled “签的是什么,为什么要签”当你的应用轮询时,FortressFlag 用两样东西作答:负载(客户端平面上是你的设备的 flag 值,服务端平面上是完整的 ruleset),以及对该负载精确字节的一个签名。签名用一把只有 FortressFlag 持有的私钥生成;你的 SDK 用随它一起发布的、与之配对的公钥来检查。
如果字节在我们的服务器和你的应用之间的任何地方被改动过——一个代理、一个 CDN、设备上被谁编辑过的缓存文件——检查就会失败,SDK 会忽略这个响应。它继续提供它最后验证过的值(见回退承诺),而不是信任它无法担保的字节。
签名不做的两件事,免得有人过度依赖它:
- 它不隐藏任何东西。负载没有加密——客户端密钥设计上就是公开的,针对它提供的一切也是。不要把机密或你用户的个人数据放进规则里。
- 它不取代 TLS。SDK 同样通过 HTTPS 与 FortressFlag 通信;签名是第二道锁,用于路径上 TLS 覆盖不到的部分(缓存、设备上的存储)。
每个 SDK 都有一个签名策略,带两个设置:
required——默认值。SDK 用它信任的密钥验证每一个负载,并拒绝任何未签名的、用它不认识的密钥签名的、或对不同字节签名的东西。在每一个与 FortressFlag 通信的构建里,你要的都是这个。disabled——接受未签名的负载。它只为一种情况而存在:对着一个没有配置签名密钥的本地 FortressFlag 后端运行。它是一个有名字、能 grep 到的设置,而不是一个无声的回退,所以“为什么这没有在验证?“在你自己的源码里总能找到答案。绝不要带着它发布生产构建。
中间没有“警告”模式。一个负载要么通过验证,要么被忽略。
你的应用信任的密钥
Section titled “你的应用信任的密钥”FortressFlag 用每个环境一把密钥签名,而 SDK 发布时只信任生产密钥。如果你对着 staging(fortressflag.net)测试,请把 staging 密钥显式加入你的 SDK 的信任密钥。
| 环境 | 密钥 ID | 公钥(base64url) |
|---|---|---|
生产(fortressflag.com) |
prod-2026-09-k1 |
EaEF8MHNu3onHxemTg3-OcrKrq7ODsZIVEp-IVV2ojg |
Staging(fortressflag.net) |
staging-2026-09-k1 |
RHFhzt8i3hQ4NKv_IrB92YuXmyNfDXx8eWN8cOrEBc8 |
同样的密钥以原始字节的十六进制形式给出,如果你的配置要的是这种格式:
prod-2026-09-k1 11a105f0c1cdbb7a271f17a64e0dfe39cacaaeaece0ec648544a7e215576a238staging-2026-09-k1 447161cedf22de143834abff22b07dd98b979b235f0d7c7c79637c70eac405cf每把密钥都是一个 32 字节的 Ed25519 公钥。密钥 ID 是每个签名的中间部分(ed25519:prod-2026-09-k1:…),SDK 就是靠它知道该用哪把密钥来检查。这些值是公开的——你可以毫无顾虑地把它们粘贴进配置文件或仓库。
当 FortressFlag 轮换密钥时,新的公钥先随一个 SDK 版本发布,而我们只在外面的 SDK 已经信任它之后才开始用它签名。轮换永远不会要求你在某个期限前发布应用:一个同时信任旧密钥和新密钥的 SDK 全程持续验证。
如果你在 Web 上
Section titled “如果你在 Web 上”Web SDK 用你浏览器内置的 Web Crypto 做验证。这需要 Ed25519 支持——Safari 17+、Chrome 137+、Firefox 130+——以及一个安全上下文:https:// 页面和 http://localhost。在一个纯 http:// 页面上,比如从局域网地址提供的,浏览器根本不会暴露 Web Crypto。
在浏览器无法验证的地方,SDK 不会假装它验证了,也不会把一份好的缓存扔掉。它把负载报告为无法验证,继续提供它最后验证过的值或你代码里的默认值,并把原因记录一次。用 HTTPS 提供你的应用,这种情况就永远不会出现。
- Flag 如何到达你的应用——两个平面,以及两者之下的回退承诺
- 密钥——为什么
ffc_是公开的而ffs_是机密