110 lines
3.3 KiB
Go
110 lines
3.3 KiB
Go
package weixin_ilink
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/aes"
|
|
"errors"
|
|
"strconv"
|
|
"testing"
|
|
)
|
|
|
|
func TestAESECB_RoundTrip_AllBlockBoundaries(t *testing.T) {
|
|
t.Parallel()
|
|
key := bytes.Repeat([]byte{0x42}, aes.BlockSize)
|
|
// Exercise len 0 through just past two blocks (padding edge cases).
|
|
for n := 0; n <= 2*aes.BlockSize+5; n++ {
|
|
n := n
|
|
t.Run("len="+strconv.Itoa(n), func(t *testing.T) {
|
|
t.Parallel()
|
|
pt := bytes.Repeat([]byte{0xAB}, n)
|
|
ct, err := aesECBEncrypt(key, pt)
|
|
if err != nil {
|
|
t.Fatalf("aesECBEncrypt: %v", err)
|
|
}
|
|
got, err := aesECBDecrypt(key, ct)
|
|
if err != nil {
|
|
t.Fatalf("aesECBDecrypt: %v", err)
|
|
}
|
|
if !bytes.Equal(got, pt) {
|
|
t.Fatalf("round trip mismatch: got %x want %x", got, pt)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestAESECB_EncryptPadsToBlockSize(t *testing.T) {
|
|
t.Parallel()
|
|
key := bytes.Repeat([]byte{1}, aes.BlockSize)
|
|
ct, err := aesECBEncrypt(key, []byte("abc")) // 3 bytes -> 16 after pad
|
|
if err != nil {
|
|
t.Fatalf("aesECBEncrypt: %v", err)
|
|
}
|
|
if len(ct) != aes.BlockSize {
|
|
t.Fatalf("ciphertext = %d bytes, want %d", len(ct), aes.BlockSize)
|
|
}
|
|
// Full block input -> one pad block appended.
|
|
ct2, err := aesECBEncrypt(key, bytes.Repeat([]byte{0}, aes.BlockSize))
|
|
if err != nil {
|
|
t.Fatalf("aesECBEncrypt: %v", err)
|
|
}
|
|
if len(ct2) != 2*aes.BlockSize {
|
|
t.Fatalf("full-block ciphertext = %d bytes, want %d", len(ct2), 2*aes.BlockSize)
|
|
}
|
|
}
|
|
|
|
func TestAESECB_DecryptRejectsBadLength(t *testing.T) {
|
|
t.Parallel()
|
|
key := bytes.Repeat([]byte{2}, aes.BlockSize)
|
|
cases := []int{0, 5, aes.BlockSize - 1, aes.BlockSize + 1}
|
|
for _, n := range cases {
|
|
n := n
|
|
t.Run("len="+strconv.Itoa(n), func(t *testing.T) {
|
|
t.Parallel()
|
|
_, err := aesECBDecrypt(key, make([]byte, n))
|
|
if !errors.Is(err, ErrBadCiphertext) {
|
|
t.Fatalf("err = %v, want ErrBadCiphertext", err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestAESECB_DecryptRejectsBadPadding(t *testing.T) {
|
|
t.Parallel()
|
|
key := bytes.Repeat([]byte{3}, aes.BlockSize)
|
|
// Valid ciphertext for one block with a correct pad (0x10) ...
|
|
good, err := aesECBEncrypt(key, bytes.Repeat([]byte{4}, aes.BlockSize-1))
|
|
if err != nil {
|
|
t.Fatalf("aesECBEncrypt: %v", err)
|
|
}
|
|
// ... then tamper the final pad byte so the padding check must fail.
|
|
bad := append([]byte(nil), good...)
|
|
bad[len(bad)-1] ^= 0xFF
|
|
_, err = aesECBDecrypt(key, bad)
|
|
if !errors.Is(err, ErrBadCiphertext) {
|
|
t.Fatalf("err = %v, want ErrBadCiphertext", err)
|
|
}
|
|
}
|
|
|
|
func TestAESECB_KeySizesAccepted(t *testing.T) {
|
|
t.Parallel()
|
|
// AES-128 requires a 16-byte key. Verify out-of-range keys are rejected.
|
|
if _, err := aesECBEncrypt(bytes.Repeat([]byte{1}, aes.BlockSize-1), []byte("x")); err == nil {
|
|
t.Fatal("short key: expected error, got nil")
|
|
}
|
|
if _, err := aesECBEncrypt(bytes.Repeat([]byte{1}, aes.BlockSize+1), []byte("x")); err == nil {
|
|
t.Fatal("long key: expected error, got nil")
|
|
}
|
|
}
|
|
|
|
func TestPKCS7_UnpadRejectsInvalid(t *testing.T) {
|
|
t.Parallel()
|
|
// More pad bytes than a block.
|
|
if _, err := pkcs7Unpad([]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17}, 16); !errors.Is(err, ErrBadCiphertext) {
|
|
t.Fatalf("oversize pad: err = %v, want ErrBadCiphertext", err)
|
|
}
|
|
// Zero pad byte is never valid.
|
|
if _, err := pkcs7Unpad([]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0}, 16); !errors.Is(err, ErrBadCiphertext) {
|
|
t.Fatalf("zero pad: err = %v, want ErrBadCiphertext", err)
|
|
}
|
|
}
|