
LMCache L2 静态加密实现解析基于 AES-GCM 的aesgcmSerde 设计与实战【免费下载链接】LMCacheLMCache: Supercharge Your LLM with the Fastest KV Cache Layer项目地址: https://gitcode.com/GitHub_Trending/lm/LMCache导读LMCache 的多进程MP架构中KV Cache 会被异步卸载到 L2 层远程 S3、本地磁盘、Redis 等这些落盘字节往往包含敏感的对话内容。本文围绕设计文档 docs/design/v1/distributed/serde/aesgcm.md深入讲解 LMCache 如何以serde 插件形式为 L2 层提供 AES-GCM 静态加密包括威胁模型、逐 chunk 的线格式、以cache_salt为选择器的密钥模型、完整配置参数并结合源码、测试与端到端示例脚本给出可落地的启用方式。读完本文你将掌握如何在任意 L2 adapter 上透明地开启 KV Cache 静态加密并理解其信任边界与已知局限。为什么加密要放在 serde 层在 LMCache 的分布式存储链路中L1CPU 内存与 L2远程/本地持久化存储之间的每一次往返都要经过序列化store 路径执行serializeload 路径执行deserialize。这种可逆对称变换的天然位置正是 serde 层。加密实现 lmcache/v1/distributed/serde/aesgcm.py 与量化类 serdefp8、turboquant位于同一 serde 目录并列存在但它有一个显著差异它是第一个需要每 key 上下文即cache_salt的 serde为此 serde 接口为serialize/deserialize/estimate_serialized_size增加了ObjectKey参数见 base.py 中Serializer/Deserializer的签名内容无关的量化 serde 可以忽略该参数而加密 serde 用它来选择密钥。接入方式上加密 serde 通过 factory.py 的注册表按名称暴露再由 SerdeL2AdapterWrapper 包装任意 L2 adapter。从包装器的设计文档serde_wrapper.py可以看到它的职责链store : caller → serialize → inner.store → signal store_efd load : caller → inner.load → deserialize → signal load_efd即控制器眼中它仍是一个普通 L2 adapter数据变换在内部透明完成adapter 与控制器代码零改动。lookup / unlock / delete / eviction 等元数据操作则直通内层 adapter不经过任何变换。威胁模型与适用边界加密保护的是能读取远程存储字节的一方如拥有 S3 bucket、磁盘或 RESP 数据访问权限的人。其范围界定为范围内持久化到 L2 的字节at-rest 机密性。范围外L1主机 RAM与 L0GPU持有明文因此能够访问运行中 MP server 进程的一方不在防御范围内——那是完全不同的威胁模型。换言之这是持久化层的静态加密at-rest confidentiality并非端到端加密。部署时需明确这一信任边界加密抵挡外部读盘者但不抵御进程内窥探者。算法选型AES-128/256-GCMLMCache 选择AEAD算法 AES-GCM一次完成机密性 完整性校验。设计文档给出的选型理由非常具体性能在服务器 AES-NI 硬件上AES-128 是速度最快的认证加密算法约每核 4–8 GB/s且加密运行在推理热路径之外L1↔L2而非 L0↔L1 的 CUDA-IPC 传输其开销可隐藏在 S3 延迟之后。密钥长度默认aes_bits128。AES-128 在计算上已不可破解而 KV Cache 短生命周期且可重新生成先收割后解密harvest-now-decrypt-later的长线攻击几乎不适用256作为配置旋钮提供给合规要求强制 256 位的场景。为何不是压缩压缩不改变数据的机密性且对 KV 是糟糕的匹配——高熵内容几乎压不动。量化才是体积杠杆且量化与加密是组合关系先量化、后加密。逐 chunk 线格式每个 KV chunk 在 L2 中的存储帧为[1B version][12B IV][ciphertext || 16B GCM tag]version格式字节允许方案演进而不破坏已存储 blob。IV每 chunk 全新随机 96-bit nonce明文存储IV 本身不是秘密但必须唯一——GCM 下重复的 (key, IV) 组合会破坏安全性。ciphertext ‖ tagAES-GCM 输出密文与明文等长无 paddingtag 为完整性校验。由于无 padding固定开销为29 字节/chunk1 版本 12 IV 16 tag因此 aesgcm.py 中的estimate_serialized_size返回的是精确值plaintext 29而非保守上界——这与其他可能膨胀输出的压缩类 serde 形成鲜明对比base.py 中对该接口的约定是必须返回上界而 aesgcm 可以做到精确。tag 不匹配数据被篡改或密钥错误时底层cryptography库会抛出InvalidTag包装器将其转为 load 失败 → 按cache miss处理重新抓取/重算绝不静默返回损坏数据。反序列化长度推导以dst为准load 路径的临时缓冲按estimate_serialized_size分配可能因分配器对齐而大于实际存储帧。因此 AesGcmDeserializer.deserialize 从dstKV 目标缓冲其字节数恰等于原始明文长度推导精确密文长度而非从可能被 padding 的src推导——这与fp8serde 从dst读取长度的做法一脉相承。测试 test_aesgcm.py 中的test_roundtrip_with_over_allocated_load_temp专门验证了这一场景在帧尾追加 64 字节垃圾数据后deserialize仍能正确还原明文。密钥模型cache_salt是选择器不是密钥这是本设计的核心安全语义。cache_salt是公开的它明文出现在 L2 对象名中它只负责选择用哪把密钥真正的秘密材料来自可替换的KeyProvider抽象接口定义见 key_provider.py。HkdfKeyProvider默认随仓库发布实现 从一个主密钥从master_key_path指向的文件读取例如挂载的 K8sSecret经HKDF-SHA256派生出每个cache_salt的独立密钥key(salt) HKDF-SHA256(master_key, infoprefix cache_salt)派生结果按 salt 缓存带锁线程安全——serde 线程池可能并发调用get_key。其中info前缀固定为lmcache-l2-aesgcm-v1源码中的_HKDF_INFO_PREFIX用于域分离保证不同加密方案派生的密钥互不冲突。信任模型fleet vs. outside。任何持有主密钥的人都能推导出所有租户的密钥因此它保护的是 L2 字节免受外部人读取不提供租户之间的相互隔离。KeyringKeyProvider规划中未实现面向每租户独立发放密钥KMS / per-tenant mount的真正跨租户隔离代价是真实的密钥分发/轮换成本。当前未实现工厂会对key_providerkeyring直接抛ValueErroraesgcm.py 与测试test_factory_unsupported_provider均可佐证。空cache_salt是合法租户桶匿名流量的空cache_salt被视为一个有效的租户桶HKDF 接受空的info并为其推导稳定密钥。测试test_empty_salt_roundtrips验证了这一行为。配置SerdeConfig.kwargs完整参数加密 serde 通过 L2 adapter 配置中的serdeJSON 子对象启用SerdeConfig的定义见 base.py工厂解析逻辑见 aesgcm.py。参数如下Key默认值含义key_providerhkdf密钥来源当前仅hkdf已实现master_key_path—主密钥文件路径hkdf必填aes_bits128128或256其余值如192被工厂拒绝max_workers1serde 线程池大小工厂的行为要点均有对应测试缺少master_key_path或文件为空 →ValueErrortest_factory_missing_master_key_pathaes_bits192→ValueErrortest_factory_bad_aes_bits成功构建时返回AsyncSerdeProcessor将同步的 Serializer/Deserializer 包装为带 eventfd 完成通知的异步接口async_processor.py接口约定见 base.py。实际配置示例磁盘 L2 aesgcm仓库提供了完整的端到端示例脚本 examples/serde/aesgcm/run_serde_aesgcm_example.sh其中 L2 adapter 的配置形如{ type: fs, base_path: /tmp/lmcache_serde_aesgcm_example/disk, serde: { type: aesgcm, key_provider: hkdf, master_key_path: /tmp/lmcache_serde_aesgcm_example/master.key, aes_bits: 128 } }该脚本从生成主密钥开始完整演示了加密存储 → 清空 L1 → L2 预取解密的闭环并给出了一个非常实用的可验证检查点落盘文件的第一个字节应为0x01帧版本字节而非原始 KV 数据——这是确认加密确实生效的最快方法。端到端启用流程基于仓库示例以下步骤取自 run_serde_aesgcm_example.sh前置条件已安装 vLLM 与 lmcache CLI1 张可用 GPU生成主密钥切勿入库或打日志# AES-128 → 16 字节AES-256 → 32 字节 head -c 16 /dev/urandom $MASTER_KEY_PATH chmod 600 $MASTER_KEY_PATH启动 LMCache MP server启用 CPU L1 磁盘 L2fs adapter aesgcm serdelmcache server \ --l1-size-gb 20 \ --eviction-policy LRU \ --l2-store-policy default \ --l2-prefetch-policy default \ --l2-adapter $L2_ADAPTER_JSON \ --port 6555 \ --http-port 8080启动 vLLM通过LMCacheMPConnector接入kv_connector_extra_config指向 lmcache 的 ZMQ 端口。带cache_salt发送推理请求冷路径L1 → L2 加密落盘等待数秒让存储控制器刷盘用ls/xxd验证 L2 文件首字节为01。清空 L1 缓存curl -X POST http://localhost:8080/cache/clear。重发同一请求L1 miss → L2 命中 → 预取加密字节 → AES-GCM 解密还原 KVvLLM 直接从缓存继续。注意请求体中的cache_salt字段如示例中的tenant-a同时是租户身份选择器与密钥选择器两次请求必须携带相同 salt 才能命中彼此的密文。正确性与隔离性的测试证据test_aesgcm.py 不依赖 GPU 或 L1Manager用暴露.byte_array的 ctypes 缓冲替身验证纯变换与工厂接线其用例覆盖了本文讨论的全部关键性质精确开销estimate_serialized_size恒等于 明文 29含单/多 tensor group 两种布局往返还原加密 → 解密恢复原始明文包括 load 临时缓冲被 padding 的场景随机 IV同一明文 同一密钥两次加密产生不同密文租户隔离alicesalt 加密的帧无法用bobsalt 解密InvalidTag完整性翻转一个 tag 字节即触发InvalidTag畸形帧版本字节/长度异常 →ValueErrorAES-256 往返、空 salt 往返、工厂参数校验。已知局限与后续工作设计文档明确列出了本 serde不解决的问题这是判断该方案适用场景的重要边界元数据泄露内容加密不隐藏 L2 对象元数据——cache_salt租户身份与内容派生的chunk_hash仍明文存在于对象名中bucket 观察者无需解密即可看到哪个租户存了什么以及跨租户内容重叠。收口该问题需单独的元数据加固步骤对 chunk hash 加盐、在入口对 salt 做假名化。每租户密钥隔离KeyringKeyProvider 租户→节点放置规划中未实现。信任模型边界主密钥持有者fleet可推导全部租户密钥加密不提供租户间隔离对运行中进程的访问者同样不在防御范围内。从源码结构看这两项后续工作keyring工厂分支、元数据加盐在设计上均已预留扩展点KeyProvider抽象接口 帧首的 version 字节未来可通过注册新 provider / 升级帧格式平滑演进。小结aesgcmserde 是 LMCache 分布式缓存安全能力的关键一环它以 29 字节/chunk 的精确固定开销在 L1↔L2 链路上提供 AES-GCM 认证加密通过cache_salt驱动的 HKDF 派生实现每租户密文不同并以 serde 插件形式零侵入地挂接到任意 L2 adapter。它解决的是L2 静态机密性这一明确问题其信任边界不防进程内窥探、不隐藏元数据、不隔离租户间密钥同样清晰。对需要将 KV Cache 落盘到共享 S3/磁盘的部署这是当前仓库内开箱即用、且有完整测试与示例支撑的推荐方案。【免费下载链接】LMCacheLMCache: Supercharge Your LLM with the Fastest KV Cache Layer项目地址: https://gitcode.com/GitHub_Trending/lm/LMCache创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考