如果blockSize的大小 小于 inputFile指定文件内容大小,解密失败
如果
blockSize 的大小小于 inputFile 指定文件的内容大小,确实可能会导致解密失败。这是因为 GCM 模式在加密和解密时需要处理完整的加密块,而分块处理时可能会破坏加密块的完整性。为了解决这个问题,我们需要确保在分块处理时,每个块的大小能够正确对齐 GCM 的加密块。问题分析
-
GCM 模式的特点:
-
GCM 模式在加密时会附加一个认证标签(tag),通常为 16 字节。
-
解密时,GCM 会验证这个标签,确保数据的完整性和真实性。
-
如果加密块的大小不正确(例如,最后一个块不完整),解密时会失败。
-
-
分块处理的挑战:
-
如果
blockSize不是加密块大小的整数倍,可能会导致最后一个块的大小不正确。 -
解密时,最后一个块可能无法正确验证认证标签。
-
解决方案
为了确保分块处理的正确性,我们需要在加密和解密时处理完整的加密块。可以通过以下方式实现:
-
确保
blockSize是加密块大小的整数倍。 -
在加密时记录每个块的大小,并在解密时正确处理每个块。
修复后的代码
以下是修复后的代码,确保分块处理时每个块的大小正确对齐 GCM 的加密块:
go
package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"fmt"
"io"
"os"
)
// encryptFileWithBlocks 使用 AES-GCM 模式按块加密文件
func encryptFileWithBlocks(inputFile, outputFile string, key []byte, blockSize int) error {
// 打开输入文件
file, err := os.Open(inputFile)
if err != nil {
return fmt.Errorf("打开输入文件失败: %w", err)
}
defer file.Close()
// 创建输出文件
outFile, err := os.Create(outputFile)
if err != nil {
return fmt.Errorf("创建输出文件失败: %w", err)
}
defer outFile.Close()
// 创建 AES 加密块
block, err := aes.NewCipher(key)
if err != nil {
return fmt.Errorf("创建加密块失败: %w", err)
}
// 创建 GCM 模式
aesgcm, err := cipher.NewGCM(block)
if err != nil {
return fmt.Errorf("创建 GCM 模式失败: %w", err)
}
// 生成随机的 nonce
nonce := make([]byte, aesgcm.NonceSize())
if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
return fmt.Errorf("生成 nonce 失败: %w", err)
}
// 将 nonce 写入输出文件
if _, err := outFile.Write(nonce); err != nil {
return fmt.Errorf("写入 nonce 失败: %w", err)
}
// 按块读取并加密文件内容
buffer := make([]byte, blockSize)
for {
n, err := file.Read(buffer)
if err != nil && err != io.EOF {
return fmt.Errorf("读取输入文件内容失败: %w", err)
}
if n == 0 {
break
}
// 加密当前块
ciphertext := aesgcm.Seal(nil, nonce, buffer[:n], nil)
// 将加密内容写入输出文件
if _, err := outFile.Write(ciphertext); err != nil {
return fmt.Errorf("写入加密内容失败: %w", err)
}
}
return