SM4-XTS 存储加密模式深度解析:从磁盘加密到 Linux fscrypt 国密实战
前言
在国密改造中,大家往往关注传输层(TLS/SSL)的国密替换,却忽略了静态数据加密(Data at Rest)的合规要求。等保2.0 四级和 GB/T 39786-2021 明确要求:重要数据在存储时必须采用密码技术确保机密性。
磁盘加密/存储加密的首选模式是 XTS(XEX-based Tweaked CodeBook mode with CipherText Stealing),它定义于 IEEE 1619-2017 和 NIST SP 800-38E,是 AES-XTS(如 LUKS、BitLocker、FileVault)的底层模式。Linux 内核 5.10+ 的 fscrypt 子系统已支持 SM4-XTS,意味着国密存储加密在操作系统层面已具备原生支持。
本文将从 XTS 的数学原理出发,深入解析 SM4-XTS 的工程实现,并给出可落地的部署方案。
XTS 模式原理
为什么需要 XTS?
传统分组密码模式(ECB、CBC)不适合磁盘加密:
| 模式 | 问题 |
|---|---|
| ECB | 相同明文块产生相同密文块,泄露数据模式 |
| CBC | 需要串行处理,无法随机访问;IV 管理复杂 |
| CTR | 计数器重复会导致密钥流重用,且无完整性保护 |
XTS 的双密钥结构
XTS 使用两个独立密钥:
- Key1(数据加密密钥):用于加密明文块
- Key2(tweak 加密密钥):用于加密扇区号(tweak value)
- 总密钥长度 = 256 位(Key1 128 位 + Key2 128 位)
- 等价于 AES-256-XTS(也是双 128 位密钥)
XTS 加密流程
设扇区索引为 $i$,块索引为 $j$,块大小 16 字节:
1. 用 Key2 加密扇区号 i,得到 tweak 值:T = SM4(Key2, i)
2. 对 tweak 值做 GF(2^128) 域乘法:T_j = T ⊗ α^j
(α 是 GF(2^128) 的本原元,即多项式 x)
3. 异或混合:X = P_j ⊕ T_j
4. 加密:E_j = SM4(Key1, X)
5. 再次异或:C_j = E_j ⊕ T_j最后一块如果不足 16 字节,使用 CipherText Stealing(CTS)处理,避免填充带来的存储膨胀。
XTS 的安全边界
XTS 的设计保证:
- 同一扇区内,相同明文在不同位置产生不同密文(tweak 不同)
- 不同扇区,相同明文产生不同密文(扇区号不同)
SM4-XTS 与 AES-XTS 对比
算法结构对比
| 维度 | SM4-XTS | AES-XTS |
|---|---|---|
| 分组大小 | 128 位 | 128 位 |
| 密钥结构 | Key1(128) + Key2(128) = 256 位 | Key1(128) + Key2(128) = 256 位 |
| 轮数 | 32 轮 | 10 轮(AES-128)/ 14 轮(AES-256) |
| S 盒 | 8 位输入 8 位输出(仿射变换) | 8 位输入 8 位输出(乘法逆元) |
| 扩散层 | 线性变换 L(B) = B ⊕ (B <<< 2) ⊕ (B <<< 10) ⊕ ... | MixColumns + ShiftRows |
| 设计年代 | 2006 年(公开 2012) | 1998 年(公开 2001) |
性能对比
在支持 SM4 硬件加速的平台上(如鲲鹏 920、海光 C86),SM4-XTS 性能接近 AES-XTS。在纯软件实现中,AES 通常更快(因为 AES-NI 指令集成熟)。
实测数据参考(来源:OpenSSL 3.0 speed 测试,Intel i7-10700,单核):
| 模式 | 吞吐量 (MB/s) | 说明 |
|---|---|---|
| AES-256-XTS(AES-NI) | ~4500 | 硬件加速(OpenSSL 3.0 speed aes-256-xts) |
| SM4-XTS(纯软件) | ~800 | 无硬件加速 |
| SM4-XTS(ARM CE) | ~3200 | ARMv8 加密扩展 |
注:以上数据为量级参考,实际性能受 CPU 型号、内存频率、数据块大小影响。SM4 硬件加速在国产 CPU(鲲鹏、海光、飞腾)上表现更优。建议部署前使用 openssl speed -evp sm4-xts 等命令进行实际基准测试。
安全性对比
两者在 XTS 模式下均提供 128 位安全性(受限于分组大小)。XTS 模式本身将有效安全强度降低约 20 位(tweak 碰撞),因此实际安全边界约为 2^60 个块(约 16 EB 数据),远超单磁盘容量。
Linux fscrypt SM4-XTS 实战
环境要求
- Linux 内核 ≥ 5.10(fscrypt 支持 SM4-XTS)
- fscrypt 工具 ≥ 1.4
- 国密内核模块(
sm4驱动)
# 检查内核 crypto 支持
cat /proc/crypto | grep -i sm4
# 检查 fscrypt 版本
fscrypt --version部署步骤
#### 1. 配置 fscrypt 使用 SM4-XTS
fscrypt 的加密算法配置位于 /etc/fscrypt.conf。当前使用 fscrypt 1.4+ 时,可通过配置文件指定默认加密算法:
# 创建加密目录
mkdir /encrypted_data
# 初始化 fscrypt 守护进程
fscrypt setup
# 创建/修改配置文件指定 SM4-XTS 为默认算法
cat > /etc/fscrypt.conf << 'EOF'
{
"source": "custom_passphrase",
"options": {
"padding": "4096",
"contents": "AES_256_XTS",
"filenames": "AES_256_CTS"
},
"policy_version": "2"
}
EOF
# 注意:截至 Linux 6.x 内核,fscrypt 用户态工具尚未原生支持 SM4-XTS 的自动配置
# 需要通过 dm-crypt/LUKS 或直接调用内核 crypto API 实现 SM4-XTS
# 以下展示基于 dm-crypt 的替代方案⚠️ 重要说明:截至 2026 年初,fscrypt 用户态工具(google/fscrypt)尚未在 CLI 中直接暴露 SM4-XTS 选项,但在内核 v5.10+ 的 crypto API 中已完整支持 SM4-XTS。实际部署中需通过 LUKS2 或 dm-crypt 的 capi: 语法调用国密算法。下方给出生产可用的 dm-crypt + SM4-XTS 方案。
#### 2. 基于 LUKS2/dm-crypt 部署 SM4-XTS(推荐)# 检查内核是否支持 SM4-XTS(capi 语法)
grep -r "sm4" /proc/crypto
# 使用 dm-crypt capi: 语法创建 SM4-XTS 加密卷
# 密钥格式:<密钥十六进制字符串>(256位 = 64个十六进制字符)
dmsetup create sm4-xts-vol --table "0 $(blockdev --getsz /dev/sdX) \
capi:xts-sm4-256 $(python3 -c "import os; print(os.urandom(32).hex() + os.urandom(32).hex())") \
0 /dev/sdX 0"
# 挂载使用
mkfs.ext4 /dev/mapper/sm4-xts-vol
mount /dev/mapper/sm4-xts-vol /encrypted_data#### 3. 密钥管理
dm-crypt/LUKS2 使用 密钥派生函数(KDF)从用户口令生成加密密钥:
口令 → PBKDF2-SHA512(迭代 500,000 次)→ 256 位主密钥⚠️ 国密合规说明:PBKDF2 算法本身是 GM/T 0054-2018 认可的 KDF 方法。在纯国密方案中,可使用 PBKDF2-SM3(用 SM3 替代 SHA-512 作为 HMAC 基础哈希),但当前 cryptsetup/LUKS2 默认使用 SHA-512/SHA-256,尚未原生支持 SM3-based KDF。部署时需评估密评机构是否接受 SHA-512 的 KDF。密钥存储在 Linux 密钥环(keyring)中,卸载后自动清除。
#### 4. 验证加密状态
# 查看 dm-crypt 加密设备状态
dmsetup status sm4-xts-vol
# 查看内核 crypto 使用情况
cryptsetup status sm4-xts-vol性能调优
对于大文件顺序读写,建议:
确保 SM4 驱动使用异步 crypto 接口:
# 查看 SM4 驱动是否支持异步
cat /proc/crypto | grep sm4
# 查看 driver 行,如果显示 "async" 则说明驱动使用了异步接口使用 dm-crypt 时启用 no_read_workqueue/no_write_workqueue 优化(Linux 5.9+):
# 使用 kernel 5.9+ 的 dm-crypt 优化
dmsetup create crypt --table "0 <sectors> crypt capi:cbc-sm4-plain <key> 0 <dev> 0 1 no_read_workqueue"注:Linux 内核 5.10+ 的 fscrypt 使用工作队列(workqueue)分发加密请求,现代内核已自动优化调度。对于鲲鹏/海光等内置 SM4 硬件加速的平台,确保加载正确的内核驱动即可自动利用硬件加速。
等保/密评合规映射
GB/T 39786-2021 存储加密要求
GB/T 39786-2021《信息安全技术 信息系统密码应用基本要求》在"设备和计算安全"层面要求:
应采用密码技术对重要数据进行机密性保护。SM4-XTS 满足以下合规要点:
| 合规要求 | SM4-XTS 实现 |
|---|---|
| 算法合规 | SM4 为国密算法(GM/T 0001-2012) |
| 模式合规 | XTS 为 IEEE 1619 / NIST SP 800-38E 标准模式 |
| 密钥长度 | 256 位(双 128 位密钥),满足等保要求 |
| 密钥管理 | fscrypt 使用 PBKDF2 派生,密钥不落地 |
密评注意事项
在密评(GM/T 0054-2018)中,存储加密的常见扣分项:
- 密钥与数据同存储:加密密钥必须与加密数据物理分离
- 无完整性校验:XTS 不提供完整性,需额外使用 HMAC-SM3 或 SM4-GCM
- 密钥未轮换:LUKS2 支持密钥槽轮换,需定期执行
cryptsetup luksChangeKey
常见问题与踩坑
坑1:内核不支持 SM4-XTS
现象:dm-crypt 或应用层调用 SM4-XTS 时报错 Algorithm not found
原因:内核未编译 SM4 模块或版本过低
解决:
# 检查内核配置
grep CONFIG_CRYPTO_SM4 /boot/config-$(uname -r)
# 应看到 CONFIG_CRYPTO_SM4=m 或 =y
# 如未编译,需重新编译内核或升级内核版本坑2:XTS 模式下数据可被篡改
现象:攻击者修改密文后,解密得到被篡改的明文,系统无感知
原因:XTS 设计不提供完整性保护
解决:叠加完整性保护层。以下是使用 gmssl 库实现 HMAC-SM3 的示例:
# 使用 HMAC-SM3 为每个扇区添加完整性标签
# 需要: pip install gmssl
import hmac
import struct
from gmssl import sm3
def hmac_sm3(key: bytes, data: bytes) -> bytes:
"""使用 SM3 实现 HMAC"""
# HMAC-SHA256 的国密替代方案
return hmac.new(key, data, sm3.sm3_hash).digest()
def compute_sector_mac(key: bytes, sector_data: bytes, sector_index: int) -> bytes:
"""计算扇区的 HMAC-SM3 完整性标签"""
mac_key = hmac_sm3(key, b"sector_mac")
return hmac_sm3(mac_key, sector_data + struct.pack("<Q", sector_index))[:16]验证说明:上述代码需要安装#### 坑3:使用 LUKS2 密钥轮换替代 fscrypt rotategmssl库。在无法安装第三方库的场景下,也可使用hashlib调用 OpenSSL 3.0+ 内置的 SM3 实现(如果编译时启用了国密支持)。
由于 fscrypt metadata rotate 命令在当前版本中不存在,对于使用 LUKS2/dm-crypt 的场景,可通过以下方式轮换密钥:
# 轮换 LUKS2 密钥槽
cryptsetup luksChangeKey /dev/sdX --key-slot 0
# 或添加新密钥槽后删除旧槽
cryptsetup luksAddKey /dev/sdX --key-slot 1
cryptsetup luksKillSlot /dev/sdX 0总结
SM4-XTS 是国密存储加密的核心技术,其优势在于:
- 标准化:XTS 模式有 IEEE 1619 和 NIST SP 800-38E 双重标准支撑
- 原生支持:Linux 内核 5.10+ 原生支持 SM4-XTS,可通过 dm-crypt/LUKS2 直接调用
- 随机访问:扇区级加密支持任意位置读写,无需解密整个磁盘
- 合规映射:直接满足 GB/T 39786-2021 对存储加密的机密性要求
部署建议:当前 fscrypt 用户态工具尚未原生支持 SM4-XTS 的自动配置,生产环境建议通过 LUKS2/dm-crypt 的 capi:xts-sm4-256 语法部署。随着 Linux 内核和 cryptsetup 工具的演进,原生 fscrypt + SM4-XTS 的方案将逐步完善。
参考来源
- IEEE 1619-2017: Standard for Cryptographic Protection of Data on Block-Oriented Storage Devices
- NIST SP 800-38E: Recommendation for Block Cipher Modes of Operation: The XTS-AES Mode for Confidentiality on Storage Devices
- GM/T 0001-2012: SM4 分组密码算法
- GB/T 32907-2016: SM4 分组密码算法(修订)
- GB/T 39786-2021: 信息安全技术 信息系统密码应用基本要求
- GM/T 0054-2018: 信息系统密码应用基本要求
- Linux fscrypt 文档: https://www.kernel.org/doc/html/latest/filesystems/fscrypt.html