fish2018/pansou · critical

创建AES加密器失败

Error message

创建AES加密器失败: %w

What it means

DecryptURL builds an AES block cipher from the package-level AESKey via aes.NewCipher. Go's crypto/aes only accepts 16, 24, or 32-byte keys; any other key length makes NewCipher fail, and the error is wrapped as 创建AES加密器失败. This indicates the configured key constant is not a valid AES key size.

Solutions

  1. Print/measure len([]byte(AESKey)) and make it exactly 16, 24, or 32 bytes.
  2. If the key is stored hex- or base64-encoded, decode it before assigning AESKey.
  3. Restore the default SDSO AESKey known to work with the site if a custom key was introduced.
  4. Add a package init check that fails fast when len(AESKey) not in {16,24,32}.

Example fix

// before
const AESKey = "my-secret-key"
// after
// key must be exactly 16/24/32 bytes
const AESKey = "0123456789abcdef" // 16 bytes
Defensive patterns

Strategy: validation

Validate before calling

key := []byte(AESKey)
if n := len(key); n != 16 && n != 24 && n != 32 {
    return fmt.Errorf("AESKey must be 16/24/32 bytes, got %d", n)
}

Type guard

func hasValidAESKeySize(key []byte) bool {
    return len(key) == 16 || len(key) == 24 || len(key) == 32
}

Prevention

When it happens

Trigger: AESKey is set to a string whose byte length is not 16/24/32 — e.g. a short placeholder, a hex-encoded key pasted as raw text, or a config value read from environment/config that is empty or the wrong length.

Common situations: Developer replaced the default key with a custom one that is e.g. 20 characters; key loaded from env var left empty; key stored hex/base64-encoded but passed without decoding.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07). Data as JSON: /api/errors/3cde326b1ba6c4d3. Report an issue: GitHub.

Appendix: source

Thrown at plugin/sdso/sdso.go:402

	ciphertext, err := base64.StdEncoding.DecodeString(encryptedURL)
	if err != nil {
		return "", fmt.Errorf("Base64解码失败: %w", err)
	}

	// 检查密文长度
	if len(ciphertext) == 0 {
		return "", fmt.Errorf("密文长度为0")
	}

	// 检查密文长度是否为16的倍数
	if len(ciphertext)%aes.BlockSize != 0 {
		return "", fmt.Errorf("密文长度不是AES块大小的倍数")
	}

	// 创建AES块加密器
	block, err := aes.NewCipher([]byte(AESKey))
	if err != nil {
		return "", fmt.Errorf("创建AES加密器失败: %w", err)
	}

	// 创建CBC模式解密器
	iv := []byte(AESIV)
	if len(iv) != aes.BlockSize {
		return "", fmt.Errorf("IV长度不正确: 期望%d,实际%d", aes.BlockSize, len(iv))
	}

	mode := cipher.NewCBCDecrypter(block, iv)

	// 解密
	plaintext := make([]byte, len(ciphertext))
	mode.CryptBlocks(plaintext, ciphertext)

	// 去除PKCS7填充
	unpaddedText, err := removePKCS7Padding(plaintext)
	if err != nil {
		return "", fmt.Errorf("去除填充失败: %w", err)

View on GitHub (pinned to beaa561337)