完善不同加密方法的使用
This commit is contained in:
@@ -0,0 +1,199 @@
|
||||
package cipherx_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/aes"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"code.yun.ink/pkg/encryptx/cipherx"
|
||||
)
|
||||
|
||||
// testSuite 返回一个以 AES 为实现、覆盖两种密钥长度的套件。
|
||||
func testSuite() *cipherx.Suite {
|
||||
return cipherx.NewSuite("TEST", aes.NewCipher, 16, 16, 32)
|
||||
}
|
||||
|
||||
func TestSuiteMetadata(t *testing.T) {
|
||||
suite := testSuite()
|
||||
|
||||
if got := suite.Name(); got != "TEST" {
|
||||
t.Errorf("Name() = %q, 期望 TEST", got)
|
||||
}
|
||||
if got := suite.BlockSize(); got != 16 {
|
||||
t.Errorf("BlockSize() = %d, 期望 16", got)
|
||||
}
|
||||
sizes := suite.KeySizes()
|
||||
if len(sizes) != 2 || sizes[0] != 16 || sizes[1] != 32 {
|
||||
t.Errorf("KeySizes() = %v, 期望 [16 32]", sizes)
|
||||
}
|
||||
|
||||
// KeySizes 必须返回副本,改动它不应影响套件本身
|
||||
sizes[0] = 999
|
||||
if again := suite.KeySizes(); again[0] != 16 {
|
||||
t.Error("KeySizes 返回了内部切片,调用方可意外篡改套件配置")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSuiteNewBlockValidatesKeyLength(t *testing.T) {
|
||||
suite := testSuite()
|
||||
|
||||
for _, size := range []int{16, 32} {
|
||||
key := bytes.Repeat([]byte{0x11}, size)
|
||||
if _, err := suite.NewBlock(key); err != nil {
|
||||
t.Errorf("NewBlock(密钥长度 %d) 失败: %v", size, err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, size := range []int{0, 8, 15, 17, 24, 31, 64} {
|
||||
key := bytes.Repeat([]byte{0x11}, size)
|
||||
if _, err := suite.NewBlock(key); !errors.Is(err, cipherx.ErrInvalidKeySize) {
|
||||
t.Errorf("NewBlock(密钥长度 %d): 期望 ErrInvalidKeySize, 得到 %v", size, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestSuiteWithoutKeySizes 验证未声明密钥长度时由底层实现校验,
|
||||
// 且失败仍被统一归类为 ErrInvalidKeySize(Blowfish 走的就是这条路径)。
|
||||
func TestSuiteWithoutKeySizes(t *testing.T) {
|
||||
suite := cipherx.NewSuite("NOCHECK", aes.NewCipher, 16)
|
||||
|
||||
if _, err := suite.NewBlock(bytes.Repeat([]byte{0x11}, 16)); err != nil {
|
||||
t.Fatalf("合法的 16 字节密钥被拒绝: %v", err)
|
||||
}
|
||||
if _, err := suite.NewBlock(bytes.Repeat([]byte{0x11}, 17)); !errors.Is(err, cipherx.ErrInvalidKeySize) {
|
||||
t.Errorf("非法密钥长度: 期望 ErrInvalidKeySize, 得到 %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSuiteEncryptDecryptAllModes(t *testing.T) {
|
||||
suite := testSuite()
|
||||
key := bytes.Repeat([]byte{0x42}, 32)
|
||||
plaintext := []byte("suite 往返测试 payload")
|
||||
|
||||
modes := []cipherx.Mode{cipherx.ECB, cipherx.CBC, cipherx.CFB, cipherx.OFB, cipherx.CTR}
|
||||
for _, mode := range modes {
|
||||
ciphertext, err := suite.Encrypt(mode, plaintext, key)
|
||||
if err != nil {
|
||||
t.Fatalf("%s: Encrypt 失败: %v", mode, err)
|
||||
}
|
||||
decrypted, err := suite.Decrypt(mode, ciphertext, key)
|
||||
if err != nil {
|
||||
t.Fatalf("%s: Decrypt 失败: %v", mode, err)
|
||||
}
|
||||
if !bytes.Equal(decrypted, plaintext) {
|
||||
t.Errorf("%s: 往返不一致", mode)
|
||||
}
|
||||
}
|
||||
|
||||
// 密钥长度非法时必须在构造阶段就失败
|
||||
if _, err := suite.Encrypt(cipherx.CBC, plaintext, []byte("short")); !errors.Is(err, cipherx.ErrInvalidKeySize) {
|
||||
t.Errorf("Encrypt 非法密钥: 期望 ErrInvalidKeySize, 得到 %v", err)
|
||||
}
|
||||
if _, err := suite.Decrypt(cipherx.CBC, []byte("x"), []byte("short")); !errors.Is(err, cipherx.ErrInvalidKeySize) {
|
||||
t.Errorf("Decrypt 非法密钥: 期望 ErrInvalidKeySize, 得到 %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSuiteWithIV(t *testing.T) {
|
||||
suite := testSuite()
|
||||
key := bytes.Repeat([]byte{0x42}, 16)
|
||||
iv := bytes.Repeat([]byte{0x7E}, 16)
|
||||
plaintext := []byte("explicit iv via suite")
|
||||
|
||||
for _, mode := range []cipherx.Mode{cipherx.CBC, cipherx.CFB, cipherx.OFB, cipherx.CTR} {
|
||||
ciphertext, err := suite.EncryptWithIV(mode, plaintext, key, iv)
|
||||
if err != nil {
|
||||
t.Fatalf("%s: EncryptWithIV 失败: %v", mode, err)
|
||||
}
|
||||
decrypted, err := suite.DecryptWithIV(mode, ciphertext, key, iv)
|
||||
if err != nil {
|
||||
t.Fatalf("%s: DecryptWithIV 失败: %v", mode, err)
|
||||
}
|
||||
if !bytes.Equal(decrypted, plaintext) {
|
||||
t.Errorf("%s: WithIV 往返不一致", mode)
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := suite.EncryptWithIV(cipherx.CBC, plaintext, key, []byte("bad")); !errors.Is(err, cipherx.ErrInvalidIVSize) {
|
||||
t.Errorf("非法 IV 长度: 期望 ErrInvalidIVSize, 得到 %v", err)
|
||||
}
|
||||
if _, err := suite.EncryptWithIV(cipherx.ECB, plaintext, key, iv); !errors.Is(err, cipherx.ErrInvalidMode) {
|
||||
t.Errorf("ECB 传 IV: 期望 ErrInvalidMode, 得到 %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSuiteHexHelpers(t *testing.T) {
|
||||
suite := testSuite()
|
||||
key := bytes.Repeat([]byte{0x42}, 16)
|
||||
iv := bytes.Repeat([]byte{0x7E}, 16)
|
||||
plaintext := []byte("hex 辅助函数")
|
||||
|
||||
for _, mode := range []cipherx.Mode{cipherx.ECB, cipherx.CBC, cipherx.CFB, cipherx.OFB, cipherx.CTR} {
|
||||
hexStr, err := suite.EncryptHex(mode, plaintext, key)
|
||||
if err != nil {
|
||||
t.Fatalf("%s: EncryptHex 失败: %v", mode, err)
|
||||
}
|
||||
decrypted, err := suite.DecryptHex(mode, hexStr, key)
|
||||
if err != nil {
|
||||
t.Fatalf("%s: DecryptHex 失败: %v", mode, err)
|
||||
}
|
||||
if !bytes.Equal(decrypted, plaintext) {
|
||||
t.Errorf("%s: Hex 往返不一致", mode)
|
||||
}
|
||||
}
|
||||
|
||||
// 带显式 IV 的十六进制辅助函数
|
||||
for _, mode := range []cipherx.Mode{cipherx.CBC, cipherx.CFB, cipherx.OFB, cipherx.CTR} {
|
||||
hexStr, err := suite.EncryptWithIVHex(mode, plaintext, key, iv)
|
||||
if err != nil {
|
||||
t.Fatalf("%s: EncryptWithIVHex 失败: %v", mode, err)
|
||||
}
|
||||
decrypted, err := suite.DecryptWithIVHex(mode, hexStr, key, iv)
|
||||
if err != nil {
|
||||
t.Fatalf("%s: DecryptWithIVHex 失败: %v", mode, err)
|
||||
}
|
||||
if !bytes.Equal(decrypted, plaintext) {
|
||||
t.Errorf("%s: WithIVHex 往返不一致", mode)
|
||||
}
|
||||
}
|
||||
|
||||
// 非法十六进制
|
||||
if _, err := suite.DecryptHex(cipherx.CBC, "zz", key); err == nil {
|
||||
t.Error("非法十六进制期望错误")
|
||||
}
|
||||
if _, err := suite.EncryptWithIVHex(cipherx.CBC, plaintext, []byte("short"), iv); !errors.Is(err, cipherx.ErrInvalidKeySize) {
|
||||
t.Errorf("非法密钥: 期望 ErrInvalidKeySize, 得到 %v", err)
|
||||
}
|
||||
if _, err := suite.DecryptWithIVHex(cipherx.CBC, "zz", key, iv); err == nil {
|
||||
t.Error("非法十六进制期望错误")
|
||||
}
|
||||
}
|
||||
|
||||
// TestSuiteMemberVariants 覆盖 Suite 各方法的失败分支,确保错误在
|
||||
// 构造阶段就被发现,而不是留到更难排查的位置。
|
||||
func TestSuiteMemberVariants(t *testing.T) {
|
||||
suite := testSuite()
|
||||
key := bytes.Repeat([]byte{0x42}, 16)
|
||||
iv := bytes.Repeat([]byte{0x7E}, 16)
|
||||
|
||||
if _, err := suite.Encrypt(cipherx.Mode(99), []byte("x"), key); !errors.Is(err, cipherx.ErrInvalidMode) {
|
||||
t.Errorf("Encrypt 非法模式: 期望 ErrInvalidMode, 得到 %v", err)
|
||||
}
|
||||
if _, err := suite.Decrypt(cipherx.Mode(99), []byte("x"), key); !errors.Is(err, cipherx.ErrInvalidMode) {
|
||||
t.Errorf("Decrypt 非法模式: 期望 ErrInvalidMode, 得到 %v", err)
|
||||
}
|
||||
if _, err := suite.EncryptWithIV(cipherx.Mode(99), []byte("x"), key, iv); !errors.Is(err, cipherx.ErrInvalidMode) {
|
||||
t.Errorf("EncryptWithIV 非法模式: 期望 ErrInvalidMode, 得到 %v", err)
|
||||
}
|
||||
if _, err := suite.DecryptWithIV(cipherx.Mode(99), []byte("x"), key, iv); !errors.Is(err, cipherx.ErrInvalidMode) {
|
||||
t.Errorf("DecryptWithIV 非法模式: 期望 ErrInvalidMode, 得到 %v", err)
|
||||
}
|
||||
|
||||
if _, err := suite.EncryptHex(cipherx.CBC, []byte("x"), []byte("short")); !errors.Is(err, cipherx.ErrInvalidKeySize) {
|
||||
t.Errorf("EncryptHex 非法密钥: 期望 ErrInvalidKeySize, 得到 %v", err)
|
||||
}
|
||||
if _, err := suite.DecryptWithIV(cipherx.CBC, []byte("x"), key, []byte("bad")); !errors.Is(err, cipherx.ErrInvalidIVSize) {
|
||||
t.Errorf("DecryptWithIV 非法 IV: 期望 ErrInvalidIVSize, 得到 %v", err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user