Files
hyapi-server/internal/infrastructure/external/huibo/crypto_test.go

433 lines
10 KiB
Go
Raw Normal View History

2026-06-01 13:15:37 +08:00
package huibo
import (
"encoding/base64"
"testing"
)
// 测试 MD5 加密(固定密文对比验证)
func TestMD5Encrypt(t *testing.T) {
appKey := "a6c9935e967894e731c62ecfcd9b7c95"
testCases := []struct {
name string
data string
expected string // 固定密文
}{
{
name: "姓名",
data: "何志勇",
expected: "64d4d5c6457026117a4911acf189e269", // 固定密文
},
{
name: "身份证号",
data: "452528197907133014",
expected: "7c6cc77dabb83d95948904dba5a7219d", // 固定密文
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
// 加密
result := MD5Encrypt(tc.data, appKey)
// 最核心:对比是否和固定密文一致
if result != tc.expected {
t.Errorf("加密不匹配!\n明文%s\n期望密文%s\n实际密文%s",
tc.data, tc.expected, result)
return
}
// 打印成功日志
t.Logf("✅ 校验成功\n明文%s\n密文%s", tc.data, result)
})
}
}
// 测试 HMAC-SHA256 签名
func TestHMACSHA256Base64(t *testing.T) {
secret := "test_secret_key"
testCases := []struct {
name string
data string
secret string
}{
{
name: "简单字符串",
data: "hello world",
secret: secret,
},
{
name: "JSON数据",
data: `{"name":"张三","idCard":"110101199003072345"}`,
secret: secret,
},
{
name: "URL参数",
data: "idCard=110101199003072345&name=张三&productCode=22089",
secret: secret,
},
{
name: "空字符串",
data: "",
secret: secret,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
result := HMACSHA256Base64(tc.data, tc.secret)
// 验证结果不为空
if result == "" {
t.Error("HMAC-SHA256签名结果为空")
}
// 验证结果是有效的Base64
_, err := base64.StdEncoding.DecodeString(result)
if err != nil {
t.Errorf("HMAC-SHA256结果不是有效的Base64: %v", err)
}
// 验证相同输入产生相同输出
result2 := HMACSHA256Base64(tc.data, tc.secret)
if result != result2 {
t.Error("相同输入产生的签名不一致")
}
// 验证不同输入产生不同输出
result3 := HMACSHA256Base64(tc.data+"x", tc.secret)
if result == result3 {
t.Error("不同输入产生的签名相同")
}
t.Logf("数据: %s, 签名: %s", tc.data, result)
})
}
}
// 测试 AES-GCM 加密解密
func TestEncryptDecryptAESGCMBase64(t *testing.T) {
// 生成一个有效的 Base64 编密的 AES 密钥
key := make([]byte, 32) // AES-256
for i := range key {
key[i] = byte(i)
}
base64Key := base64.StdEncoding.EncodeToString(key)
testCases := []struct {
name string
data string
}{
{
name: "简单文本",
data: "hello world",
},
{
name: "中文文本",
data: "你好世界",
},
{
name: "JSON数据",
data: `{"name":"张三","idCard":"110101199003072345"}`,
},
{
name: "长文本",
data: "这是一个很长的文本用来测试加密解密功能是否正常工作。包含各种字符123456789!@#$%^&*()_+-=[]{}|;':\",./<>?",
},
{
name: "空字符串",
data: "",
},
{
name: "特殊字符",
data: "\n\t\r\x00",
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
// 加密
encrypted, err := EncryptAESGCMBase64(tc.data, base64Key)
if err != nil {
t.Fatalf("加密失败: %v", err)
}
// 验证加密结果不为空
if encrypted == "" {
t.Error("加密结果为空")
}
// 验证加密结果是有效的Base64
_, err = base64.StdEncoding.DecodeString(encrypted)
if err != nil {
t.Errorf("加密结果不是有效的Base64: %v", err)
}
// 验证加密结果与原文不同
if encrypted == tc.data {
t.Error("加密结果与原文相同")
}
// 解密
decrypted, err := DecryptAESGCMBase64(encrypted, base64Key)
if err != nil {
t.Fatalf("解密失败: %v", err)
}
// 验证解密结果与原文一致
if decrypted != tc.data {
t.Errorf("解密结果不匹配,期望: %s, 实际: %s", tc.data, decrypted)
}
t.Logf("原文: %s", tc.data)
t.Logf("密文: %s", encrypted)
t.Logf("解密: %s", decrypted)
})
}
}
// 测试错误的密钥
func TestEncryptDecryptWithWrongKey(t *testing.T) {
// 生成两个不同的密钥
key1 := make([]byte, 32)
for i := range key1 {
key1[i] = byte(i)
}
base64Key1 := base64.StdEncoding.EncodeToString(key1)
key2 := make([]byte, 32)
for i := range key2 {
key2[i] = byte(i + 1)
}
base64Key2 := base64.StdEncoding.EncodeToString(key2)
data := "sensitive data"
// 用密钥1加密
encrypted, err := EncryptAESGCMBase64(data, base64Key1)
if err != nil {
t.Fatalf("加密失败: %v", err)
}
// 用密钥2解密
decrypted, err := DecryptAESGCMBase64(encrypted, base64Key2)
if err == nil {
t.Error("用错误密钥解密应该返回错误")
}
// 验证解密结果与原文不同(如果解密成功的话)
if decrypted == data {
t.Error("用错误密钥解密不应该得到正确结果")
}
t.Logf("用错误密钥解密预期失败: %v", err)
}
// 测试无效的 Base64 密钥
func TestEncryptWithInvalidBase64Key(t *testing.T) {
data := "test data"
invalidKeys := []string{
"", // 空字符串
"not_base64", // 非Base64
"abc", // 解码后太短
}
for _, invalidKey := range invalidKeys {
_, err := EncryptAESGCMBase64(data, invalidKey)
if err == nil {
t.Errorf("使用无效密钥 %s 应该返回错误", invalidKey)
}
t.Logf("无效密钥 %s 预期失败: %v", invalidKey, err)
}
}
// 测试解密无效数据
func TestDecryptWithInvalidData(t *testing.T) {
// 生成一个有效的密钥
key := make([]byte, 32)
for i := range key {
key[i] = byte(i)
}
base64Key := base64.StdEncoding.EncodeToString(key)
invalidData := []string{
"", // 空字符串
"invalid_base64", // 非Base64
"dGVzdA==", // 有效的Base64但不是AES-GCM数据
"short", // 太短
}
for _, data := range invalidData {
_, err := DecryptAESGCMBase64(data, base64Key)
if err == nil {
t.Errorf("使用无效数据 %s 应该返回错误", data)
}
t.Logf("无效数据 %s 预期失败: %v", data, err)
}
}
// 测试加密结果的唯一性
func TestEncryptionUniqueness(t *testing.T) {
// 生成一个有效的密钥
key := make([]byte, 32)
for i := range key {
key[i] = byte(i)
}
base64Key := base64.StdEncoding.EncodeToString(key)
data := "same data"
// 加密多次
results := make([]string, 10)
for i := 0; i < 10; i++ {
encrypted, err := EncryptAESGCMBase64(data, base64Key)
if err != nil {
t.Fatalf("第%d次加密失败: %v", i, err)
}
results[i] = encrypted
}
// 验证每次加密结果都不同因为包含随机IV
uniqueCount := 0
for i := 0; i < len(results); i++ {
isUnique := true
for j := 0; j < len(results); j++ {
if i != j && results[i] == results[j] {
isUnique = false
break
}
}
if isUnique {
uniqueCount++
}
}
if uniqueCount != len(results) {
t.Errorf("加密结果应该唯一,实际上只有%d个唯一结果期望%d个", uniqueCount, len(results))
}
t.Logf("生成了%d个不同的加密结果", uniqueCount)
}
// 测试使用真实配置的加密解密
func TestEncryptionWithRealConfig(t *testing.T) {
// 使用配置文件中的真实AES密钥
aesKey := "NQYN3YO+pb/GEcCBNX0ptMb7cUlnXSPvcX7VvNofBkc="
appKey := "a6c9935e967894e731c62ecfcd9b7c95"
// 测试数据
testData := `{"name":"张三","idCard":"110101199003072345","productCode":"22089"}`
t.Run("MD5加密", func(t *testing.T) {
// 测试 MD5 加密
md5Result := MD5Encrypt("张三", appKey)
t.Logf("姓名 MD5: %s", md5Result)
md5Result2 := MD5Encrypt("110101199003072345", appKey)
t.Logf("身份证号 MD5: %s", md5Result2)
// 验证格式
if len(md5Result) != 32 {
t.Errorf("MD5结果长度错误期望32位实际%d位", len(md5Result))
}
})
t.Run("HMAC-SHA256签名", func(t *testing.T) {
// 生成排序后的参数
sortedParam := "idCard=110101199003072345&name=张三&productCode=22089"
signature := HMACSHA256Base64(sortedParam, aesKey)
t.Logf("签名参数: %s", sortedParam)
t.Logf("HMAC-SHA256签名: %s", signature)
// 验证格式
_, err := base64.StdEncoding.DecodeString(signature)
if err != nil {
t.Errorf("签名不是有效的Base64: %v", err)
}
})
t.Run("AES-GCM加密解密", func(t *testing.T) {
// 测试 AES-GCM 加密
encrypted, err := EncryptAESGCMBase64(testData, aesKey)
if err != nil {
t.Fatalf("加密失败: %v", err)
}
t.Logf("原始数据: %s", testData)
t.Logf("加密结果: %s", encrypted)
// 测试解密
decrypted, err := DecryptAESGCMBase64(encrypted, aesKey)
if err != nil {
t.Fatalf("解密失败: %v", err)
}
t.Logf("解密结果: %s", decrypted)
// 验证结果
if decrypted != testData {
t.Errorf("解密结果不匹配")
}
})
}
// 基准测试
func BenchmarkMD5Encrypt(b *testing.B) {
data := "张三"
appKey := "a6c9935e967894e731c62ecfcd9b7c95"
b.ResetTimer()
for i := 0; i < b.N; i++ {
MD5Encrypt(data, appKey)
}
}
func BenchmarkHMACSHA256Base64(b *testing.B) {
data := "idCard=110101199003072345&name=张三"
secret := "a6c9935e967894e731c62ecfcd9b7c95"
b.ResetTimer()
for i := 0; i < b.N; i++ {
HMACSHA256Base64(data, secret)
}
}
func BenchmarkEncryptAESGCMBase64(b *testing.B) {
data := `{"name":"张三","idCard":"110101199003072345","productCode":"22089"}`
// 生成密钥
key := make([]byte, 32)
for i := range key {
key[i] = byte(i)
}
base64Key := base64.StdEncoding.EncodeToString(key)
b.ResetTimer()
for i := 0; i < b.N; i++ {
EncryptAESGCMBase64(data, base64Key)
}
}
func BenchmarkDecryptAESGCMBase64(b *testing.B) {
data := `{"name":"张三","idCard":"110101199003072345","productCode":"22089"}`
// 生成密钥
key := make([]byte, 32)
for i := range key {
key[i] = byte(i)
}
base64Key := base64.StdEncoding.EncodeToString(key)
// 先加密一次
encrypted, err := EncryptAESGCMBase64(data, base64Key)
if err != nil {
b.Fatalf("预加密失败: %v", err)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
DecryptAESGCMBase64(encrypted, base64Key)
}
}