A2 版本 - 高性能并行加密
📋 概述
A2 版本是 A1 的升级版,主要改进:
- 将 AES-CBC 替换为 AES-GCM 加密模式
- 默认使用多核并行加密/解密,显著提升性能
- 修复 GCM nonce 重用安全问题
- 提供 AEAD 认证加密,防止数据篡改
- 简化代码结构,优化性能
🔐 加密方案
核心技术
- RSA 4096位: 用于加密 AES 密钥和配置
- AES-256-GCM: 用于加密实际数据 (AEAD 认证加密)
- 多核并行: 充分利用多核 CPU 性能
- tar.xz: 用于数据压缩
加密流程
原始文件/目录
↓
tar 打包
↓
xz 压缩
↓
分块 (64KB 块)
↓
并行 AES-GCM 加密
↓
添加文件头
↓
加密压缩包
📦 加密文件结构
完整结构布局
┌────────────────────────────────────────────────────┐
│ 版本头 (2 字节) │
│ ┌──────────┬──────────┐ │
│ │ Protocol │ Version │ │
│ │ 'A' │ 2 │ │
│ │ (1 byte) │ (1 byte) │ │
│ └──────────┴──────────┘ │
├────────────────────────────────────────────────────┤
│ 文件头 (14 字节) │
│ ┌──────────────┬────────────────────────────┐ │
│ │ IsEncryption │ Padding │ │
│ │ (bool) │ (13 bytes) │ │
│ │ (1 byte) │ │ │
│ └──────────────┴────────────────────────────┘ │
├────────────────────────────────────────────────────┤
│ [如果加密] RSA 加密的 AES 配置 (512 字节) │
│ │
│ RSA-4096 加密的二进制数据: │
│ ┌──────────────────────────────────────┐ │
│ │ Nonce (12 bytes) - GCM 基础 nonce │ │
│ │ Key (32 bytes) - AES-256 密钥 │ │
│ │ Salt (16 bytes) - 盐值 │ │
│ └──────────────────────────────────────┘ │
│ 总共 60 字节,RSA 加密后固定 512 字节 │
│ │
│ 使用公钥加密,私钥解密 │
├────────────────────────────────────────────────────┤
│ [如果加密] AES-GCM 加密数据块序列 │
│ │
│ ┌────────────────────────────────────────┐ │
│ │ 数据块 0: │ │
│ │ ┌──────────────┐ │ │
│ │ │ 块长度 │ uint32, 4 bytes │ │
│ │ ├──────────────┤ │ │
│ │ │ 密文 + 标签 │ N bytes + 16 bytes │ │
│ │ └──────────────┘ │ │
│ ├────────────────────────────────────────┤ │
│ │ 数据块 1: │ │
│ │ ┌──────────────┐ │ │
│ │ │ 块长度 │ uint32, 4 bytes │ │
│ │ ├──────────────┤ │ │
│ │ │ 密文 + 标签 │ N bytes + 16 bytes │ │
│ │ └──────────────┘ │ │
│ ├────────────────────────────────────────┤ │
│ │ ... 更多数据块 ... │ │
│ ├────────────────────────────────────────┤ │
│ │ 最后一块: │ │
│ │ ┌──────────────┐ │ │
│ │ │ 块长度 │ uint32, 4 bytes │ │
│ │ ├──────────────┤ │ │
│ │ │ 密文 + 标签 │ M bytes + 16 bytes │ │
│ │ └──────────────┘ │ │
│ └────────────────────────────────────────┘ │
│ │
│ 每个块使用唯一的 nonce (基础nonce XOR 块索引) │
│ 支持多核并行加密/解密 │
├────────────────────────────────────────────────────┤
│ tar.xz 压缩数据 │
│ │
│ 原始数据经过 tar 打包 + xz 压缩后的结果 │
└────────────────────────────────────────────────────┘
详细字段说明
1. 版本头 (2 字节)
| 字段 |
类型 |
大小 |
值 |
说明 |
| Protocol |
byte |
1 |
'A' (0x41) |
协议标识符 |
| Version |
uint8 |
1 |
2 |
版本号 |
编码方式: Big Endian 二进制
2. 文件头 (14 字节)
| 字段 |
类型 |
大小 |
说明 |
| IsEncryption |
bool |
1 |
是否加密 (true=加密, false=未加密) |
| Padding |
byte[] |
13 |
填充字节(保留用于未来扩展) |
编码方式: Big Endian 二进制
3. RSA 加密块 (512 字节,仅加密时存在)
大小: 固定 512 字节 (RSA-4096 密文长度)
内容: 使用 RSA 公钥加密的二进制格式 AES 配置
解密后的二进制结构 (60 字节):
| 字段 |
类型 |
大小 |
说明 |
| Nonce |
[12]byte |
12 |
GCM 基础 nonce |
| Key |
[32]byte |
32 |
AES-256 密钥 |
| Salt |
[16]byte |
16 |
盐值(保留) |
编码方式: Big Endian 二进制
RSA 加密参数:
- 算法: RSA PKCS#1 v1.5
- 密钥长度: 4096 位
- 明文长度: 60 字节
- 密文固定长度: 512 字节
兼容性说明: A2 也能解密旧版本使用 JSON 格式的配置块。
4. AES-GCM 加密数据块 (仅加密时存在)
加密参数:
- 算法: AES-256-GCM
- 密钥长度: 256 位 (32 字节)
- Nonce 长度: 96 位 (12 字节)
- 认证标签: 128 位 (16 字节)
- 默认块大小: 64 KB
数据块格式:
每个数据块包含两部分:
-
块长度 (4 字节):
- 类型: uint32
- 编码: Big Endian
- 值: 密文长度(包含 16 字节认证标签)
- 范围: 17 - 65552 字节(1 字节明文 + 标签 到 64KB + 标签)
-
密文数据 (变长):
- GCM 加密后的数据
- 自动包含 16 字节认证标签(在密文末尾)
- 长度 = 原始数据长度 + 16
块索引与 Nonce:
每个数据块使用唯一的 nonce,生成规则:
块 nonce (12 字节) = 基础 nonce (12 字节) XOR (前4字节为0 + 块索引8字节)
例如:
基础 nonce: [A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, AA, AB]
块 0 索引: [00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00]
块 0 nonce: [A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, AA, AB]
块 1 索引: [00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 01]
块 1 nonce: [A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, AA, AA]
块 2 索引: [00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 02]
块 2 nonce: [A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, AA, A9]
这确保了:
- ✅ 每个块的 nonce 都唯一
- ✅ 支持最多 2^64 个块
- ✅ GCM 安全性要求得到满足
并行处理:
- 加密时:多个工作线程并行加密不同块
- 解密时:多个工作线程并行解密不同块
- 结果排序:确保输出顺序正确
- 工作线程数:默认等于 CPU 核心数
5. tar.xz 压缩数据
实际的文件/目录内容,经过以下处理:
- 使用 tar 格式打包
- 使用 xz (LZMA2) 算法压缩
- 然后进行 AES-GCM 加密(如果启用)
🔧 技术细节
Nonce 生成算法
// 为指定块索引生成唯一的 nonce
func generateNonce(blockIndex uint64, baseNonce []byte) []byte {
nonce := make([]byte, 12)
copy(nonce, baseNonce) // 复制基础 nonce (12 字节)
// 将块索引转换为 8 字节
indexBytes := make([]byte, 8)
binary.BigEndian.PutUint64(indexBytes, blockIndex)
// 与 nonce 的后 8 字节进行 XOR
for i := 0; i < 8; i++ {
nonce[4+i] ^= indexBytes[i]
}
return nonce
}
AES-GCM 加密
// 加密数据块(可变大小,≤64KB)
func AesGCMEncrypt(plaintext, key, nonce []byte) ([]byte, error) {
block, err := aes.NewCipher(key) // 256位密钥
if err != nil {
return nil, err
}
aesgcm, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
// Seal 会自动添加 16 字节认证标签
ciphertext := aesgcm.Seal(nil, nonce, plaintext, nil)
return ciphertext, nil
}
RSA 加密
// 加密 AES 配置(二进制格式)
func encryptConfig(a2 *A2, pubKey []byte) ([]byte, error) {
block := struct {
Nonce [12]byte
Key [32]byte
Salt [16]byte
}{
Nonce: [12]byte(a2.aes.Nonce),
Key: [32]byte(a2.aes.Key),
Salt: [16]byte(a2.aes.Salt),
}
var buf bytes.Buffer
binary.Write(&buf, binary.BigEndian, block)
return rsa.Encrypt(buf.Bytes(), pubKey)
}
📊 文件大小计算
加密文件大小
总大小 = 版本头 + 文件头 + RSA块 + 加密数据块总大小
= 2 + 14 + 512 + Σ(4 + 块密文长度 + 16)
每个数据块:
块大小 = 4 (长度字段) + 明文大小 + 16 (GCM 标签)
示例
| 压缩数据大小 |
加密块数 |
每块大小 |
总文件大小 |
| 100 字节 |
1 |
4 + 100 + 16 = 120 |
648 字节 |
| 64 KB |
1 |
4 + 65536 + 16 = 65556 |
66,084 字节 |
| 65 KB |
2 |
65556 + 1044 = 66600 |
67,128 字节 |
| 1 MB |
17 |
约 1,048,848 |
1,049,376 字节 |
| 10 MB |
161 |
约 10,486,416 |
10,486,944 字节 |
开销分析:
- 固定开销: 528 字节(版本头 + 文件头 + RSA块)
- 每块开销: 20 字节(4字节长度 + 16字节标签)
- 总开销率: (528 + 块数 × 20) / 总大小
对于大文件,开销率非常低(< 0.1%)。
未加密文件大小
总大小 = 版本头 + 文件头 + 压缩数据
= 2 + 14 + 压缩数据大小
🚀 并行加密架构
AES-GCM vs AES-CBC
| 特性 |
A1 (AES-CBC) |
A2 (AES-GCM) |
| 加密模式 |
CBC (密码块链接) |
GCM (伽罗瓦计数器) |
| 认证 |
无 |
内置认证标签 (AEAD) |
| 并行性 |
加密串行,解密可并行 |
加密和解密都并行 |
| 块大小 |
512 字节 |
64 KB |
| 填充 |
随机填充 |
不需要填充 |
| 性能 |
中等 |
高 (多核优化) |
| 安全性 |
高 |
更高 (防篡改) |
| IV/Nonce |
固定 IV |
每块唯一 nonce |
Nonce 唯一性保证
GCM 模式下,nonce 必须唯一,否则会导致严重的安全问题。
A2 的 nonce 生成策略:
nonce (12 字节) = 随机基础nonce(12字节) XOR (0填充(4字节) + 块索引(8字节))
- 基础 nonce:每次加密生成新的 12 字节随机数
- 块索引:从 0 开始递增的 64 位整数
这确保了:
- 不同文件间 nonce 不同(随机基础 nonce)
- 同一文件内不同块 nonce 不同(块索引)
- 支持最多 2^64 个块(几乎无限)
🚀 并行加密优化
架构设计
┌─────────────────┐
│ 输入数据流 │
└────────┬─────────┘
│
┌────────────▼────────────┐
│ 缓冲区 (64KB 块) │
└────────────┬────────────┘
│
┌────────────▼────────────┐
│ 任务队列 (16 缓冲) │
└────────────┬────────────┘
│
┌────────────────────┼────────────────────┐
│ │ │
┌─────▼─────┐ ┌─────▼─────┐ ┌─────▼─────┐
│ Worker 1 │ │ Worker 2 │ ... │ Worker N │
│ AES-GCM │ │ AES-GCM │ │ AES-GCM │
└─────┬─────┘ └─────┬─────┘ └─────┬─────┘
│ │ │
└────────────────────┼────────────────────┘
│
┌────────────▼────────────┐
│ 结果排序 (保证顺序) │
└────────────┬────────────┘
│
┌────────▼─────────┐
│ 输出数据流 │
└──────────────────┘
工作流程
- 输入数据分块:将数据分成 64KB 的块
- 并行加密:多个工作线程同时加密不同的块
- 结果排序:按块索引顺序重新排列
- 顺序写入:确保输出文件块顺序正确
工作线程数
默认使用 runtime.NumCPU() 作为工作线程数,可以通过修改 numWorkers 常量调整。
性能提升
实际性能取决于数据大小、I/O 速度和 CPU 性能
📊 使用方法
并行模式
A2 版本默认且仅支持并行模式,自动利用多核 CPU 性能:
- 自动检测 CPU 核心数
- 启动对应数量的工作线程
- 无需手动配置
使用 A2 版本压缩
在 main.go 中修改默认版本:
var defaultVersion = model.HeadVersion{
Protocol: 'A',
Version: 2, // 使用 A2
}
或在命令行中通过参数指定(需要添加版本选择功能)。
🔧 性能调优
块大小调整
默认块大小为 64KB,可以根据场景调整:
// 小文件或低内存场景
blockSize = 1024 * 16 // 16KB
// 大文件或高性能场景
blockSize = 1024 * 256 // 256KB
建议:
- 小于 1MB 的文件:16-32KB
- 1-100MB 的文件:64-128KB
- 大于 100MB 的文件:128-256KB
队列大小调整
任务队列缓冲区大小影响内存使用和吞吐量:
// 低内存场景
queueSize = 4
// 高性能场景
queueSize = 32
🔒 安全性说明
GCM 认证加密 (AEAD)
AES-GCM 提供 AEAD (Authenticated Encryption with Associated Data):
✅ 自动认证: 每个数据块包含 16 字节认证标签
✅ 防篡改: 任何数据修改都会导致解密失败
✅ 完整性验证: 解密时自动验证数据未被篡改
✅ 并行友好: 认证和加密同时进行
工作原理:
- 加密时:
Seal() 生成密文并附加 16 字节标签
- 解密时:
Open() 验证标签,如果不匹配则返回错误
- 标签计算:基于密文、nonce、密钥和附加数据(如果有)
安全保证:
- 数据保密性:攻击者无法读取明文
- 数据完整性:任何修改都会被检测到
- 数据真实性:确认数据来自持有密钥的一方
Nonce 唯一性保证
GCM 模式的核心安全要求:同一密钥下,nonce 必须唯一
A2 的 nonce 管理策略确保绝对唯一性:
-
随机基础 nonce (12 字节):
- 每次加密文件时生成
- 使用
crypto/rand 确保随机性
- 存储在 RSA 加密块中
-
块索引 (64 位整数):
- 从 0 开始递增
- 每个块索引唯一
- 支持 2^64 个块(理论上无限)
-
XOR 组合:
最终 nonce = 基础 nonce XOR (块索引的后8字节)
安全性证明:
- 不同文件:基础 nonce 不同 → nonce 不同 ✅
- 同一文件不同块:块索引不同 → nonce 不同 ✅
- 重复加密同一文件:基础 nonce 重新生成 → nonce 不同 ✅
⚠️ 重要警告:
- 不要修改 nonce 生成逻辑
- 不要重用基础 nonce
- 不要跳过或重复块索引
📝 使用建议
适用场景
A2 版本特别适合以下场景:
✅ 高性能需求
- 处理大文件 (>100MB)
- 需要快速加密/解密
- 多核 CPU 环境
- 有充足的内存资源
✅ 安全性要求高
- 需要数据完整性验证
- 防止数据篡改
- 符合现代安全标准(AEAD)
- 金融、医疗等敏感数据
✅ 批量处理
- 大量文件并行处理
- 自动化备份系统
- CI/CD 流程集成
不适用场景
❌ 资源受限环境
- 低内存设备 (< 4GB RAM)
- 单核或双核 CPU
- 嵌入式系统
- 建议使用 A1 版本
❌ 超小文件
- 文件小于 1MB
- 并行开销大于收益
- A1 版本可能更快
性能优化建议
- SSD 存储: A2 的高性能需要快速 I/O 支撑
- 多核 CPU: 至少 4 核以上才能发挥优势
- 充足内存: 建议至少 8GB RAM
- 调整块大小: 根据文件大小调整
blockSize 常量
🎯 未来优化方向
- 自适应块大小:根据文件大小自动调整块大小
- 内存池:减少 GC 压力,提高性能
- 零拷贝优化:减少内存分配和复制
- SIMD 加速:利用 CPU 向量指令加速 AES 计算
- GPU 加速:对超大文件使用 GPU 并行加密
- 流式处理:支持管道和流式数据源
- 增量压缩:只压缩变化的部分