数据加密
v17 凭据加密配置、原密钥保留与 v18 准备
本文固定已发布的 Core v17.0.4。v18 已删除关闭加密和旧格式写入,不能沿用下文的 v17 逃生口,详见 v18 准备说明。
三种秘密分别保管
| 秘密 | 用途 | 恢复时的要求 |
|---|---|---|
MX_ENCRYPT_KEY / ENCRYPT_KEY | 配置、Snippet、Webhook 的字段加密 | 保留产生这些密文的原密钥 |
JWT_SECRET | 登录与 Better Auth OAuth token 加密 | 保留原值;轮换需要维护窗口 |
| 备份恢复私钥 | 打开 .mxbackup 归档 | 与备份分开保存;不能替代上面两种秘密 |
已有实例不要为解决解密错误而生成新密钥。新密钥无法解开旧数据。先从部署配置、秘密管理器或历史快照找回原值;丢失原秘密时,需要重新授权或重新配置相应凭据。
v17 如何开启
为从未加密过的新实例生成随机字段密钥,并保存到秘密管理器:
openssl rand -hex 32将结果配置为 MX_ENCRYPT_KEY(优先)或 ENCRYPT_KEY,同时在 app 和 mx-migrate 的共享环境中启用 MX_ENCRYPT_ENABLE=true。开启时必须显式提供 64 位十六进制密钥;长度不足、非 hex、仅提供开启开关都会在启动时失败。不要依赖 machine-id 回退,也不要使用示例公共密钥。
设置密钥且未指定开关时会自动开启加密。命令行 --encrypt_key / --encrypt_enable 仍可使用;升级工具使用环境变量,不读取业务进程的 CLI/YAML 参数。
V2 写入与历史数据
MX_SECRET_STORAGE_V2=true 要求已开启字段加密,且 JWT_SECRET 至少 32 字符。它为配置、Snippet 和 Webhook 使用认证加密,为 API Key 使用哈希,为 OAuth access/refresh token 使用 Better Auth 加密。配置的密码字段由 schema 的 encrypt 元数据决定,数据库和 Redis 中均保留密文;空秘密 PATCH 保留旧值。
V2 字段密文绑定字段路径;不能把密文直接搬到另一个字段。旧明文和 ECB 保留读取与迁移能力。ENCRYPT_ALGORITHM 默认 aes-256-ecb,供旧格式使用;V2 固定使用 AES-256-GCM。
v18 已删除 ENCRYPT_ALGORITHM、--encrypt_algorithm 和 YAML encrypt_algorithm,新写入固定 AES-256-GCM。旧项即使填默认值也会报错,应删除;历史读取固定为 AES-256-ECB。使用其他历史算法的实例须先在旧版本用原密钥和原算法转换为 V2 并验证,再升级;详见 v18 准备说明。
滚动部署时,先让全部副本具备新格式读取能力,再在全部副本启用 V2,最后回填旧数据。旧 migrate:secrets 完成记录仅代表该次凭据回填,不代表已完成未来 v18 的配置与指标准备。检查与准备工具自 Core v17.1.0 起提供,见 准备流程。
v17.0.4 临时明文逃生口
只有关闭字段加密且 MX_SECRET_STORAGE_V2=false 时,普通配置写入可继续保留明文。它不适用于已有密文,也不适用于明确要求加密的授权功能。关闭开关不会解密旧数据;遇到已有密文仍须开启加密并提供原密钥。
此逃生口仅适用于已发布的 v17.0.4。v18 已经移除它,生产要求显式字段密钥、至少 32 字符的 JWT,并固定 V2 写入;旧关闭配置须删除。源码 dev 未配置字段密钥时可自动生成并保存在 tmp/dev-encryption.key,重启复用;开发库和该文件须一起保留,详见 v18 开发环境说明。
解密失败时
检查密钥来源、别名优先级、原 JWT 和密文所属路径。错误密钥、损坏密文或未知格式会失败,不会回落为明文成功。备份解封装成功也不表示归档内凭据能解密,详见 备份与恢复。