Optimize the encryption and decryption logic and fix the issues in the test
Some checks are pending
Stability Tests / Stability Tests (1.24, macos-latest) (push) Waiting to run
Stability Tests / Stability Tests (1.24, ubuntu-latest, true) (push) Waiting to run
Stability Tests / Stability Tests (1.24, windows-latest) (push) Waiting to run

This commit is contained in:
2025-03-14 16:38:16 +08:00
parent 427e7d8766
commit f1de873319
6 changed files with 1546 additions and 673 deletions

794
stdlib_comparison_test.go Normal file
View File

@@ -0,0 +1,794 @@
package xcipher
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/binary"
"fmt"
"io"
"io/ioutil"
"runtime"
"testing"
"golang.org/x/crypto/chacha20poly1305"
)
var (
benchmarkKey = make([]byte, chacha20poly1305.KeySize)
benchmarkAESKey = make([]byte, 32) // 256-bit AES key
benchmarkSmallData = make([]byte, 1024) // 1KB
benchmarkMediumData = make([]byte, 64*1024) // 64KB
benchmarkLargeData = make([]byte, 1024*1024) // 1MB
benchmarkHugeData = make([]byte, 10*1024*1024) // 10MB
)
func init() {
// 初始化测试数据
rand.Read(benchmarkKey)
rand.Read(benchmarkAESKey)
rand.Read(benchmarkSmallData)
rand.Read(benchmarkMediumData)
rand.Read(benchmarkLargeData)
rand.Read(benchmarkHugeData)
}
// 标准库 ChaCha20Poly1305 实现
func encryptWithStdChaCha20Poly1305(plaintext, additionalData []byte) ([]byte, error) {
aead, err := chacha20poly1305.NewX(benchmarkKey)
if err != nil {
return nil, err
}
nonce := make([]byte, chacha20poly1305.NonceSizeX)
if _, err := rand.Read(nonce); err != nil {
return nil, err
}
ciphertext := aead.Seal(nil, nonce, plaintext, additionalData)
result := make([]byte, len(nonce)+len(ciphertext))
copy(result, nonce)
copy(result[len(nonce):], ciphertext)
return result, nil
}
func decryptWithStdChaCha20Poly1305(ciphertext, additionalData []byte) ([]byte, error) {
aead, err := chacha20poly1305.NewX(benchmarkKey)
if err != nil {
return nil, err
}
if len(ciphertext) < chacha20poly1305.NonceSizeX {
return nil, fmt.Errorf("ciphertext too short")
}
nonce := ciphertext[:chacha20poly1305.NonceSizeX]
encrypted := ciphertext[chacha20poly1305.NonceSizeX:]
return aead.Open(nil, nonce, encrypted, additionalData)
}
// 标准库 AES-GCM 实现
func encryptWithAESGCM(plaintext, additionalData []byte) ([]byte, error) {
block, err := aes.NewCipher(benchmarkAESKey)
if err != nil {
return nil, err
}
aead, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
nonce := make([]byte, aead.NonceSize())
if _, err := rand.Read(nonce); err != nil {
return nil, err
}
ciphertext := aead.Seal(nil, nonce, plaintext, additionalData)
result := make([]byte, len(nonce)+len(ciphertext))
copy(result, nonce)
copy(result[len(nonce):], ciphertext)
return result, nil
}
func decryptWithAESGCM(ciphertext, additionalData []byte) ([]byte, error) {
block, err := aes.NewCipher(benchmarkAESKey)
if err != nil {
return nil, err
}
aead, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
if len(ciphertext) < aead.NonceSize() {
return nil, fmt.Errorf("ciphertext too short")
}
nonce := ciphertext[:aead.NonceSize()]
encrypted := ciphertext[aead.NonceSize():]
return aead.Open(nil, nonce, encrypted, additionalData)
}
// XCipher 流式加密的标准库模拟实现
func streamEncryptWithStdChaCha20Poly1305(r io.Reader, w io.Writer, additionalData []byte) error {
aead, err := chacha20poly1305.NewX(benchmarkKey)
if err != nil {
return err
}
// 写入基础随机数
baseNonce := make([]byte, chacha20poly1305.NonceSizeX)
if _, err := rand.Read(baseNonce); err != nil {
return err
}
if _, err := w.Write(baseNonce); err != nil {
return err
}
// 分块处理
buffer := make([]byte, 64*1024) // 64KB 缓冲区
blockNonce := make([]byte, chacha20poly1305.NonceSizeX)
copy(blockNonce, baseNonce)
counter := uint64(0)
for {
n, err := r.Read(buffer)
if err != nil && err != io.EOF {
return err
}
if n > 0 {
// 为每个块创建唯一的随机数
binary.LittleEndian.PutUint64(blockNonce[chacha20poly1305.NonceSizeX-8:], counter)
counter++
// 加密数据块
sealed := aead.Seal(nil, blockNonce, buffer[:n], additionalData)
// 写入加密数据块长度
lengthBytes := make([]byte, 4)
binary.BigEndian.PutUint32(lengthBytes, uint32(len(sealed)))
if _, err := w.Write(lengthBytes); err != nil {
return err
}
// 写入加密数据
if _, err := w.Write(sealed); err != nil {
return err
}
}
if err == io.EOF {
break
}
}
return nil
}
// 标准库模拟流式解密实现
func streamDecryptWithStdChaCha20Poly1305(r io.Reader, w io.Writer, additionalData []byte) error {
aead, err := chacha20poly1305.NewX(benchmarkKey)
if err != nil {
return err
}
// 读取基础随机数
baseNonce := make([]byte, chacha20poly1305.NonceSizeX)
if _, err := io.ReadFull(r, baseNonce); err != nil {
return fmt.Errorf("failed to read nonce: %v", err)
}
// 准备读取数据块
blockNonce := make([]byte, chacha20poly1305.NonceSizeX)
copy(blockNonce, baseNonce)
counter := uint64(0)
lengthBuf := make([]byte, 4)
for {
// 读取数据块长度
_, err := io.ReadFull(r, lengthBuf)
if err != nil {
if err == io.EOF {
break
}
return err
}
// 解析数据块长度
blockLen := binary.BigEndian.Uint32(lengthBuf)
encBuffer := make([]byte, blockLen)
// 读取加密数据块
_, err = io.ReadFull(r, encBuffer)
if err != nil {
return err
}
// 为每个块创建唯一的随机数
binary.LittleEndian.PutUint64(blockNonce[chacha20poly1305.NonceSizeX-8:], counter)
counter++
// 解密数据块
decrypted, err := aead.Open(nil, blockNonce, encBuffer, additionalData)
if err != nil {
return err
}
// 写入解密数据
if _, err := w.Write(decrypted); err != nil {
return err
}
}
return nil
}
// 对比基本加密性能
func BenchmarkCompareEncrypt(b *testing.B) {
testCases := []struct {
name string
size int
data []byte
}{
{"Small_1KB", 1 * 1024, benchmarkSmallData},
{"Medium_64KB", 64 * 1024, benchmarkMediumData},
{"Large_1MB", 1 * 1024 * 1024, benchmarkLargeData},
{"Huge_10MB", 10 * 1024 * 1024, benchmarkHugeData},
}
for _, tc := range testCases {
// XCipher
b.Run(fmt.Sprintf("XCipher_%s", tc.name), func(b *testing.B) {
cipher := NewXCipher(benchmarkKey)
b.ResetTimer()
b.SetBytes(int64(tc.size))
for i := 0; i < b.N; i++ {
_, err := cipher.Encrypt(tc.data, nil)
if err != nil {
b.Fatal(err)
}
}
})
// Standard ChaCha20Poly1305
b.Run(fmt.Sprintf("StdChaCha20Poly1305_%s", tc.name), func(b *testing.B) {
b.ResetTimer()
b.SetBytes(int64(tc.size))
for i := 0; i < b.N; i++ {
_, err := encryptWithStdChaCha20Poly1305(tc.data, nil)
if err != nil {
b.Fatal(err)
}
}
})
// AES-GCM
b.Run(fmt.Sprintf("AES_GCM_%s", tc.name), func(b *testing.B) {
b.ResetTimer()
b.SetBytes(int64(tc.size))
for i := 0; i < b.N; i++ {
_, err := encryptWithAESGCM(tc.data, nil)
if err != nil {
b.Fatal(err)
}
}
})
}
}
// 对比基本解密性能
func BenchmarkCompareDecrypt(b *testing.B) {
testCases := []struct {
name string
size int
data []byte
}{
{"Small_1KB", 1 * 1024, benchmarkSmallData},
{"Medium_64KB", 64 * 1024, benchmarkMediumData},
{"Large_1MB", 1 * 1024 * 1024, benchmarkLargeData},
}
for _, tc := range testCases {
// XCipher 加密准备
xcipher := NewXCipher(benchmarkKey)
xcipherEncrypted, _ := xcipher.Encrypt(tc.data, nil)
// 标准库 ChaCha20Poly1305 加密准备
stdChachaEncrypted, _ := encryptWithStdChaCha20Poly1305(tc.data, nil)
// AES-GCM 加密准备
aesGcmEncrypted, _ := encryptWithAESGCM(tc.data, nil)
// XCipher
b.Run(fmt.Sprintf("XCipher_%s", tc.name), func(b *testing.B) {
b.ResetTimer()
b.SetBytes(int64(tc.size))
for i := 0; i < b.N; i++ {
_, err := xcipher.Decrypt(xcipherEncrypted, nil)
if err != nil {
b.Fatal(err)
}
}
})
// Standard ChaCha20Poly1305
b.Run(fmt.Sprintf("StdChaCha20Poly1305_%s", tc.name), func(b *testing.B) {
b.ResetTimer()
b.SetBytes(int64(tc.size))
for i := 0; i < b.N; i++ {
_, err := decryptWithStdChaCha20Poly1305(stdChachaEncrypted, nil)
if err != nil {
b.Fatal(err)
}
}
})
// AES-GCM
b.Run(fmt.Sprintf("AES_GCM_%s", tc.name), func(b *testing.B) {
b.ResetTimer()
b.SetBytes(int64(tc.size))
for i := 0; i < b.N; i++ {
_, err := decryptWithAESGCM(aesGcmEncrypted, nil)
if err != nil {
b.Fatal(err)
}
}
})
}
}
// 对比流式加密性能
func BenchmarkCompareStreamEncrypt(b *testing.B) {
testCases := []struct {
name string
size int
data []byte
}{
{"Medium_64KB", 64 * 1024, benchmarkMediumData},
{"Large_1MB", 1 * 1024 * 1024, benchmarkLargeData},
{"Huge_10MB", 10 * 1024 * 1024, benchmarkHugeData},
}
for _, tc := range testCases {
// XCipher 顺序流式加密
b.Run(fmt.Sprintf("XCipher_Sequential_%s", tc.name), func(b *testing.B) {
xcipher := NewXCipher(benchmarkKey)
options := DefaultStreamOptions()
options.UseParallel = false
b.ResetTimer()
b.SetBytes(int64(tc.size))
for i := 0; i < b.N; i++ {
b.StopTimer()
reader := bytes.NewReader(tc.data)
writer := ioutil.Discard
b.StartTimer()
_, err := xcipher.EncryptStreamWithOptions(reader, writer, options)
if err != nil {
b.Fatal(err)
}
}
})
// XCipher 并行流式加密
b.Run(fmt.Sprintf("XCipher_Parallel_%s", tc.name), func(b *testing.B) {
xcipher := NewXCipher(benchmarkKey)
options := DefaultStreamOptions()
options.UseParallel = true
options.MaxWorkers = runtime.NumCPU()
b.ResetTimer()
b.SetBytes(int64(tc.size))
for i := 0; i < b.N; i++ {
b.StopTimer()
reader := bytes.NewReader(tc.data)
writer := ioutil.Discard
b.StartTimer()
_, err := xcipher.EncryptStreamWithOptions(reader, writer, options)
if err != nil {
b.Fatal(err)
}
}
})
// 标准库模拟流式加密
b.Run(fmt.Sprintf("StdChacha20Poly1305_Stream_%s", tc.name), func(b *testing.B) {
b.ResetTimer()
b.SetBytes(int64(tc.size))
for i := 0; i < b.N; i++ {
b.StopTimer()
reader := bytes.NewReader(tc.data)
writer := ioutil.Discard
b.StartTimer()
err := streamEncryptWithStdChaCha20Poly1305(reader, writer, nil)
if err != nil {
b.Fatal(err)
}
}
})
}
}
// 对比流式解密性能
func BenchmarkCompareStreamDecrypt(b *testing.B) {
testCases := []struct {
name string
size int
data []byte
}{
{"Medium_64KB", 64 * 1024, benchmarkMediumData},
{"Large_1MB", 1 * 1024 * 1024, benchmarkLargeData},
{"Huge_10MB", 10 * 1024 * 1024, benchmarkHugeData},
}
for _, tc := range testCases {
// 准备XCipher加密数据
xcipher := NewXCipher(benchmarkKey)
var xCipherBuf bytes.Buffer
options := DefaultStreamOptions()
options.UseParallel = false
_, _ = xcipher.EncryptStreamWithOptions(bytes.NewReader(tc.data), &xCipherBuf, options)
xCipherEncData := xCipherBuf.Bytes()
// 准备标准库加密数据
var stdBuf bytes.Buffer
_ = streamEncryptWithStdChaCha20Poly1305(bytes.NewReader(tc.data), &stdBuf, nil)
stdEncData := stdBuf.Bytes()
// XCipher 顺序流式解密
b.Run(fmt.Sprintf("XCipher_Sequential_%s", tc.name), func(b *testing.B) {
options := DefaultStreamOptions()
options.UseParallel = false
b.ResetTimer()
b.SetBytes(int64(tc.size))
for i := 0; i < b.N; i++ {
b.StopTimer()
reader := bytes.NewReader(xCipherEncData)
writer := ioutil.Discard
b.StartTimer()
_, err := xcipher.DecryptStreamWithOptions(reader, writer, options)
if err != nil {
b.Fatal(err)
}
}
})
// XCipher 并行流式解密
b.Run(fmt.Sprintf("XCipher_Parallel_%s", tc.name), func(b *testing.B) {
options := DefaultStreamOptions()
options.UseParallel = true
options.MaxWorkers = runtime.NumCPU()
b.ResetTimer()
b.SetBytes(int64(tc.size))
for i := 0; i < b.N; i++ {
b.StopTimer()
reader := bytes.NewReader(xCipherEncData)
writer := ioutil.Discard
b.StartTimer()
_, err := xcipher.DecryptStreamWithOptions(reader, writer, options)
if err != nil {
b.Fatal(err)
}
}
})
// 标准库模拟流式解密
b.Run(fmt.Sprintf("StdChacha20Poly1305_Stream_%s", tc.name), func(b *testing.B) {
b.ResetTimer()
b.SetBytes(int64(tc.size))
for i := 0; i < b.N; i++ {
b.StopTimer()
reader := bytes.NewReader(stdEncData)
writer := ioutil.Discard
b.StartTimer()
err := streamDecryptWithStdChaCha20Poly1305(reader, writer, nil)
if err != nil {
b.Fatal(err)
}
}
})
}
}
// 多核心优化性能测试
func BenchmarkMultiCoreScaling(b *testing.B) {
// 使用较大数据块展示并行处理优势
dataSize := 32 * 1024 * 1024 // 32MB
largeData := make([]byte, dataSize)
rand.Read(largeData)
// 测试在不同CPU核心数下的性能表现
maxCores := runtime.NumCPU()
for cores := 1; cores <= maxCores; cores *= 2 {
// 如果cores超过最大核心数使用最大核心数
testCores := cores
if testCores > maxCores {
testCores = maxCores
}
coreName := fmt.Sprintf("%d_Cores", testCores)
// 限制使用的CPU数量
runtime.GOMAXPROCS(testCores)
// XCipher并行加密
b.Run(fmt.Sprintf("XCipher_Parallel_%s", coreName), func(b *testing.B) {
xcipher := NewXCipher(benchmarkKey)
options := DefaultStreamOptions()
options.UseParallel = true
options.MaxWorkers = testCores
b.ResetTimer()
b.SetBytes(int64(dataSize))
for i := 0; i < b.N; i++ {
b.StopTimer()
reader := bytes.NewReader(largeData)
writer := ioutil.Discard
b.StartTimer()
_, err := xcipher.EncryptStreamWithOptions(reader, writer, options)
if err != nil {
b.Fatal(err)
}
}
})
// 标准库加密
b.Run(fmt.Sprintf("StdChaCha20Poly1305_%s", coreName), func(b *testing.B) {
b.ResetTimer()
b.SetBytes(int64(dataSize))
for i := 0; i < b.N; i++ {
b.StopTimer()
reader := bytes.NewReader(largeData)
writer := ioutil.Discard
b.StartTimer()
err := streamEncryptWithStdChaCha20Poly1305(reader, writer, nil)
if err != nil {
b.Fatal(err)
}
}
})
}
// 恢复默认的CPU核心数设置
runtime.GOMAXPROCS(runtime.NumCPU())
}
// HardwareAccelerationTest 测试硬件加速性能
func BenchmarkHardwareAcceleration(b *testing.B) {
// 测试不同算法在硬件加速下的性能表现
dataSize := 16 * 1024 * 1024 // 16MB
data := make([]byte, dataSize)
rand.Read(data)
// 获取CPU架构信息
info := GetSystemOptimizationInfo()
// ChaCha20-Poly1305XCipher
b.Run(fmt.Sprintf("XCipher_HW=%v_AVX2=%v", true, info.HasAVX2), func(b *testing.B) {
cipher := NewXCipher(benchmarkKey)
// 使用优化选项
options := GetOptimizedStreamOptions()
b.ResetTimer()
b.SetBytes(int64(dataSize))
for i := 0; i < b.N; i++ {
b.StopTimer()
reader := bytes.NewReader(data)
writer := ioutil.Discard
b.StartTimer()
_, err := cipher.EncryptStreamWithOptions(reader, writer, options)
if err != nil {
b.Fatal(err)
}
}
})
// 标准库 ChaCha20-Poly1305
b.Run(fmt.Sprintf("StdChaCha20Poly1305_HW=%v", true), func(b *testing.B) {
b.ResetTimer()
b.SetBytes(int64(dataSize))
for i := 0; i < b.N; i++ {
b.StopTimer()
reader := bytes.NewReader(data)
writer := ioutil.Discard
b.StartTimer()
err := streamEncryptWithStdChaCha20Poly1305(reader, writer, nil)
if err != nil {
b.Fatal(err)
}
}
})
// AES-GCM (如果硬件支持AES-NI可能会有很好的性能)
b.Run(fmt.Sprintf("AES_GCM_HW=%v", true), func(b *testing.B) {
b.ResetTimer()
b.SetBytes(int64(dataSize))
for i := 0; i < b.N; i++ {
_, err := encryptWithAESGCM(data, nil)
if err != nil {
b.Fatal(err)
}
}
})
}
// 内存使用测试 - 检查不同大小数据时的内存分配情况
func BenchmarkMemoryUsage(b *testing.B) {
sizes := []struct {
name string
size int
}{
{"4KB", 4 * 1024},
{"1MB", 1 * 1024 * 1024},
{"10MB", 10 * 1024 * 1024},
}
for _, size := range sizes {
data := make([]byte, size.size)
rand.Read(data)
// XCipher
b.Run(fmt.Sprintf("XCipher_%s", size.name), func(b *testing.B) {
cipher := NewXCipher(benchmarkKey)
b.ResetTimer()
b.ReportAllocs() // 报告内存分配情况
for i := 0; i < b.N; i++ {
_, err := cipher.Encrypt(data, nil)
if err != nil {
b.Fatal(err)
}
}
})
// 标准库
b.Run(fmt.Sprintf("StdChaCha20Poly1305_%s", size.name), func(b *testing.B) {
b.ResetTimer()
b.ReportAllocs() // 报告内存分配情况
for i := 0; i < b.N; i++ {
_, err := encryptWithStdChaCha20Poly1305(data, nil)
if err != nil {
b.Fatal(err)
}
}
})
}
}
// 综合性能矩阵测试,对比不同算法在各种场景下的性能
func BenchmarkPerformanceMatrix(b *testing.B) {
// 测试参数矩阵
sizes := []struct {
name string
size int
}{
{"4KB", 4 * 1024},
{"64KB", 64 * 1024},
{"1MB", 1 * 1024 * 1024},
}
methods := []struct {
name string
encrypt func([]byte, []byte) ([]byte, error)
decrypt func([]byte, []byte) ([]byte, error)
}{
{
name: "XCipher",
encrypt: func(data, aad []byte) ([]byte, error) {
cipher := NewXCipher(benchmarkKey)
return cipher.Encrypt(data, aad)
},
decrypt: func(data, aad []byte) ([]byte, error) {
cipher := NewXCipher(benchmarkKey)
return cipher.Decrypt(data, aad)
},
},
{
name: "StdChaCha20Poly1305",
encrypt: encryptWithStdChaCha20Poly1305,
decrypt: decryptWithStdChaCha20Poly1305,
},
{
name: "AES_GCM",
encrypt: encryptWithAESGCM,
decrypt: decryptWithAESGCM,
},
}
// 针对每种数据大小
for _, size := range sizes {
data := make([]byte, size.size)
rand.Read(data)
// 针对每种加密方法
for _, method := range methods {
// 加密基准测试
b.Run(fmt.Sprintf("Encrypt_%s_%s", method.name, size.name), func(b *testing.B) {
b.ResetTimer()
b.SetBytes(int64(size.size))
for i := 0; i < b.N; i++ {
_, err := method.encrypt(data, nil)
if err != nil {
b.Fatal(err)
}
}
})
// 解密基准测试
encrypted, _ := method.encrypt(data, nil)
b.Run(fmt.Sprintf("Decrypt_%s_%s", method.name, size.name), func(b *testing.B) {
b.ResetTimer()
b.SetBytes(int64(size.size))
for i := 0; i < b.N; i++ {
_, err := method.decrypt(encrypted, nil)
if err != nil {
b.Fatal(err)
}
}
})
}
}
}
// 报告辅助函数 - 在测试运行期间收集相关信息
func TestPrintBenchmarkGuide(t *testing.T) {
if testing.Short() {
t.Skip("跳过报告生成")
}
fmt.Println("======= XCipher 与标准库加密性能对比测试指南 =======")
fmt.Println("运行以下命令以执行全面性能对比测试:")
fmt.Println("go test -bench=Benchmark -benchmem -benchtime=1s")
fmt.Println()
fmt.Println("或运行特定测试:")
fmt.Println("go test -bench=BenchmarkCompareEncrypt -benchmem")
fmt.Println("go test -bench=BenchmarkCompareDecrypt -benchmem")
fmt.Println("go test -bench=BenchmarkCompareStreamEncrypt -benchmem")
fmt.Println("go test -bench=BenchmarkCompareStreamDecrypt -benchmem")
fmt.Println("go test -bench=BenchmarkMultiCoreScaling -benchmem")
fmt.Println("go test -bench=BenchmarkHardwareAcceleration -benchmem")
fmt.Println("go test -bench=BenchmarkMemoryUsage -benchmem")
fmt.Println("go test -bench=BenchmarkPerformanceMatrix -benchmem")
fmt.Println()
// 获取CPU和系统信息
fmt.Println("系统信息:")
fmt.Printf("CPU: %d 核心\n", runtime.NumCPU())
fmt.Printf("GOMAXPROCS: %d\n", runtime.GOMAXPROCS(0))
fmt.Printf("架构: %s\n", runtime.GOARCH)
// 获取优化相关信息
info := GetSystemOptimizationInfo()
fmt.Println("\n硬件加速支持:")
fmt.Printf("AVX: %v\n", info.HasAVX)
fmt.Printf("AVX2: %v\n", info.HasAVX2)
fmt.Printf("SSE4.1: %v\n", info.HasSSE41)
fmt.Printf("ARM NEON: %v\n", info.HasNEON)
fmt.Println("\n推荐优化参数:")
fmt.Printf("建议缓冲区大小: %d 字节\n", info.RecommendedBufferSize)
fmt.Printf("建议工作线程数: %d\n", info.RecommendedWorkers)
fmt.Printf("并行处理阈值: %d 字节\n", info.ParallelThreshold)
fmt.Println("\n测试结果将显示各种加密算法和方法的性能差异。")
fmt.Println("=================================================")
}