Files
encryptx/chachax/sentinel_test.go
T
2026-09-30 15:49:12 +08:00

83 lines
3.5 KiB
Go

package chachax_test
import (
"errors"
"testing"
"code.yun.ink/pkg/encryptx/chachax"
)
// TestSentinelErrors 确认调用方可以用 errors.Is 区分失败类别,
// 而不必解析错误文本——这决定了上层能否把「被篡改」与「参数写错」分开处理。
func TestSentinelErrors(t *testing.T) {
key, err := chachax.GenerateKey()
if err != nil {
t.Fatalf("GenerateKey 失败: %v", err)
}
// 密钥长度错误
for _, badKey := range [][]byte{nil, {}, make([]byte, 16), make([]byte, 31), make([]byte, 33)} {
if _, _, err := chachax.Encrypt(badKey, []byte("x"), nil); !errors.Is(err, chachax.ErrInvalidKeySize) {
t.Errorf("密钥长度 %d: 期望 ErrInvalidKeySize, 得到 %v", len(badKey), err)
}
if _, _, err := chachax.EncryptX(badKey, []byte("x"), nil); !errors.Is(err, chachax.ErrInvalidKeySize) {
t.Errorf("XChaCha 密钥长度 %d: 期望 ErrInvalidKeySize, 得到 %v", len(badKey), err)
}
}
// nonce 长度错误
ciphertext, nonce, err := chachax.Encrypt(key, []byte("payload"), nil)
if err != nil {
t.Fatalf("Encrypt 失败: %v", err)
}
for _, badNonce := range [][]byte{nil, {}, make([]byte, 8), make([]byte, 24)} {
if _, err := chachax.Decrypt(key, ciphertext, badNonce, nil); !errors.Is(err, chachax.ErrInvalidNonceSize) {
t.Errorf("nonce 长度 %d: 期望 ErrInvalidNonceSize, 得到 %v", len(badNonce), err)
}
}
// XChaCha 期望 24 字节,12 字节同样应被拒
xCiphertext, xNonce, err := chachax.EncryptX(key, []byte("payload"), nil)
if err != nil {
t.Fatalf("EncryptX 失败: %v", err)
}
if _, err := chachax.DecryptX(key, xCiphertext, nonce, nil); !errors.Is(err, chachax.ErrInvalidNonceSize) {
t.Errorf("XChaCha 用 12 字节 nonce: 期望 ErrInvalidNonceSize, 得到 %v", err)
}
// 密文过短(不足认证标签)
for n := 0; n < chachax.Overhead; n++ {
if _, err := chachax.Decrypt(key, make([]byte, n), nonce, nil); !errors.Is(err, chachax.ErrCiphertextTooShort) {
t.Errorf("密文长度 %d: 期望 ErrCiphertextTooShort, 得到 %v", n, err)
}
if _, err := chachax.DecryptX(key, make([]byte, n), xNonce, nil); !errors.Is(err, chachax.ErrCiphertextTooShort) {
t.Errorf("XChaCha 密文长度 %d: 期望 ErrCiphertextTooShort, 得到 %v", n, err)
}
}
// Seal 数据过短
for n := 0; n < chachax.NonceSize+chachax.Overhead; n++ {
if _, err := chachax.Open(key, make([]byte, n), nil); !errors.Is(err, chachax.ErrCiphertextTooShort) {
t.Errorf("Open 数据长度 %d: 期望 ErrCiphertextTooShort, 得到 %v", n, err)
}
}
for n := 0; n < chachax.NonceSizeX+chachax.Overhead; n++ {
if _, err := chachax.OpenX(key, make([]byte, n), nil); !errors.Is(err, chachax.ErrCiphertextTooShort) {
t.Errorf("OpenX 数据长度 %d: 期望 ErrCiphertextTooShort, 得到 %v", n, err)
}
}
// 认证失败:篡改密文、篡改 AAD、用错密钥
tampered := append([]byte(nil), ciphertext...)
tampered[0] ^= 0x01
if _, err := chachax.Decrypt(key, tampered, nonce, nil); !errors.Is(err, chachax.ErrAuthenticationFailed) {
t.Errorf("篡改密文: 期望 ErrAuthenticationFailed, 得到 %v", err)
}
if _, err := chachax.Decrypt(key, ciphertext, nonce, []byte("wrong aad")); !errors.Is(err, chachax.ErrAuthenticationFailed) {
t.Errorf("错误 AAD: 期望 ErrAuthenticationFailed, 得到 %v", err)
}
otherKey, _ := chachax.GenerateKey()
if _, err := chachax.Decrypt(otherKey, ciphertext, nonce, nil); !errors.Is(err, chachax.ErrAuthenticationFailed) {
t.Errorf("错误密钥: 期望 ErrAuthenticationFailed, 得到 %v", err)
}
}