83 lines
3.5 KiB
Go
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)
|
|
}
|
|
}
|