3. 加密存储基础

在安全分区与加密存储系统中,密码学不是“加个密”这么简单,而是由多种算法分工协作构成的完整链条。对称加密负责大批量数据的快速保护,非对称加密解决密钥分发与身份认证,哈希算法保证完整性,密钥派生把口令变成可用密钥,加密模式与填充方案则决定数据如何被分块处理。理解它们各自的位置与边界,是设计加密存储方案的第一步。

一、核心原理:五类密码学原语的职责分工

可以把加密存储的密码学体系看作一条流水线:用户口令先经过密钥派生函数(KDF)生成主密钥,主密钥再派生出数据加密密钥(DEK);DEK 配合对称加密算法和加密模式,对分区中的每个数据块进行加密;哈希算法用于校验密文或元数据是否被篡改;非对称加密则用于保护 DEK 本身,或用于设备与服务器之间的身份认证。

  • 对称加密:加密与解密使用同一密钥,速度快、适合大数据量,典型算法有 AES-128/192/256、SM4、ChaCha20。
  • 非对称加密:公钥加密、私钥解密,或私钥签名、公钥验签,速度慢但解决密钥分发问题,典型算法有 RSA、ECC、SM2。
  • 哈希算法:单向压缩,输出固定长度摘要,用于完整性校验和口令存储,典型算法有 SHA-256、SHA-3、SM3。
  • 密钥派生:把低熵口令或共享秘密扩展为高熵密钥,典型算法有 PBKDF2、bcrypt、scrypt、Argon2、HKDF。
  • 加密模式与填充:规定分组密码如何逐块处理数据,如 ECB、CBC、CTR、GCM,以及 PKCS#7、ISO 10126 等填充方式。
核心原则:对称密钥保护数据,非对称密钥保护对称密钥,哈希保护完整性,KDF 保护口令,模式与填充决定安全边界。

二、方法流程:从口令到密文块的完整链路

下面以“用户输入口令解锁加密分区”为例,说明各原语如何串联。该流程在 LUKS、BitLocker、FileVault 等方案中都有类似结构。

用户口令
   │
   ▼
[KDF: Argon2id / PBKDF2]  ── 加盐 + 迭代 ──▶ 主密钥 MK
   │
   ▼
[密钥包装: AES-KW 或 RSA-OAEP] ──▶ 加密后的 DEK 存入元数据区
   │
   ▼
[对称加密: AES-256-XTS / AES-256-GCM]
   │
   ▼
[加密模式: XTS 按扇区加密 / GCM 带认证标签]
   │
   ▼
[填充: XTS 无需填充 / CBC 需 PKCS#7]
   │
   ▼
密文数据块 + 完整性标签

流程中有两个关键点:第一,DEK 不直接由口令生成,而是随机生成后再被主密钥包装,这样修改口令时只需重新包装 DEK,不必重新加密全部数据;第二,加密模式的选择直接影响是否需要填充,以及能否提供完整性保护。

三、加密模式与填充方案对比

分组密码本身只能加密固定长度的一块数据,加密模式定义了如何把任意长度的明文拆分成块并串联处理。填充方案则解决最后一块不足整块时如何补齐的问题。下表列出常见组合及其适用场景。

模式 是否需填充 并行能力 完整性 典型场景
ECB 需要 可并行 无 不推荐用于存储数据
CBC 需要 PKCS#7 加密串行、解密并行 无,需额外 HMAC 传统磁盘加密、文件加密
CTR 不需要 可并行 无,需额外 MAC 高速流式加密
GCM 不需要 可并行 自带认证标签 网络传输、元数据加密
XTS 不需要 按扇区并行 无,依赖上层校验 全盘/分区加密
误区一:认为 ECB 只要密钥足够长就安全。ECB 对相同明文块产生相同密文块,会泄露数据模式,绝不适合存储结构化数据。误区二:认为 CBC 自带完整性。CBC 只提供机密性,必须配合 HMAC 或改用 GCM 才能防篡改。

四、案例场景:安全分区中的密钥层级设计

假设某终端设备需要保护一个 64GB 的数据分区,同时支持用户修改口令。推荐采用三层密钥结构:

  1. 用户口令层:用户输入口令,经 Argon2id 加盐迭代生成主密钥 MK,盐值随机存储于分区头部。
  2. 密钥包装层:系统随机生成 256 位 DEK,用 MK 通过 AES-KW 包装后存入元数据区;修改口令时只需用新 MK 重新包装同一 DEK。
  3. 数据加密层:使用 AES-256-XTS 按 512 字节扇区加密数据,每个扇区使用独立的 tweak 值,避免相同明文产生相同密文。

对于分区头部等小体积元数据,可改用 AES-256-GCM,直接获得认证保护;对于需要与服务器交互的场景,可用 ECC 或 SM2 对 DEK 进行公钥包装,实现“设备加密、服务器托管恢复密钥”的能力。

# 典型 LUKS2 头部参数示例
cipher: aes-xts-plain64
key size: 512 bits (256-bit XTS key + 256-bit tweak key)
hash: sha256
PBKDF: argon2id, iterations=4, memory=1GiB, parallelism=4
sector size: 4096 bytes

五、误区与复盘:常见设计缺陷

  • 用哈希直接当加密:哈希不可逆,不能用于需要还原的数据;口令存储应使用加盐慢哈希,而不是 SHA-256 单次计算。
  • KDF 迭代次数过低:PBKDF2 若只迭代 1000 次,GPU 可快速暴力破解;应优先选择 Argon2id 并配置足够内存与迭代。
  • IV/Nonce 复用:CTR、GCM 模式下 Nonce 重复会直接泄露明文异或关系,必须保证全局唯一。
  • 填充预言攻击:CBC 模式下若解密失败信息可被区分,攻击者可逐字节推断明文,应统一错误响应或改用 GCM。
  • 密钥与数据同盘存储:DEK 包装后的密文若与数据放在同一分区且无额外保护,物理拆盘后仍可能被离线攻击。
复盘建议:在方案评审时逐项确认“数据用什么算法加密、密钥如何派生、密钥如何包装、模式是否认证、填充是否安全、Nonce 如何保证唯一”,这六个问题能覆盖绝大多数加密存储设计缺陷。
加密存储密码学原语协作关系 用户口令 低熵 · 可记忆 密钥派生 KDF Argon2id / PBKDF2 主密钥 MK 加盐 · 迭代 密钥包装 AES-KW / RSA-OAEP 数据密钥 DEK 随机生成 · 256 位 包装/解包 对称加密 AES-256 / SM4 加密模式 XTS / GCM / CBC 填充方案 PKCS#7 / 无填充 哈希算法 SHA-256 / SM3 完整性校验 摘要比对 · 防篡改 非对称加密 RSA / ECC / SM2 密文数据块 + 认证标签 写入安全分区

综上,对称加密、非对称加密、哈希、KDF、加密模式与填充并非彼此替代,而是各司其职、层层配合。设计加密存储方案时,应先明确数据保护目标,再按“口令→KDF→主密钥→包装 DEK→对称加密→模式与填充→完整性校验”的链路逐层选型,才能既保证性能,又守住安全边界。