fish2018/pansou · error
无效的填充长度
Error message
无效的填充长度: %d
What it means
removePKCS7Padding reads the last plaintext byte as the padding length and validates it is in [1, min(len(data), aes.BlockSize)]. If the value is 0, larger than the data, or larger than one AES block, the padding is structurally invalid and the function fails with 无效的填充长度. This is a strong signal that decryption produced garbage — typically a wrong AES key/IV.
Solutions
- Verify AESKey/AESIV are current for the SDSO site; wrong-key garbage decryption is the dominant cause.
- Re-fetch a fresh encrypted URL rather than decrypting cached/stale data.
- Hex-dump the decrypted plaintext and confirm the last byte looks like padding (a small 1..16 value); if random, fix the key/IV, not the padding logic.
- Confirm the upstream scheme is actually AES-CBC + PKCS7; if the site switched modes (e.g. GCM or no padding), update DecryptURL accordingly.
Example fix
// before
plaintext := make([]byte, len(ciphertext))
mode.CryptBlocks(plaintext, ciphertext)
unpaddedText, err := removePKCS7Padding(plaintext)
// after
plaintext := make([]byte, len(ciphertext))
mode.CryptBlocks(plaintext, ciphertext)
last := int(plaintext[len(plaintext)-1])
if last == 0 || last > aes.BlockSize || last > len(plaintext) {
return "", fmt.Errorf("decryption produced invalid padding %d — likely wrong AESKey/AESIV", last)
}
unpaddedText, err := removePKCS7Padding(plaintext) Defensive patterns
Strategy: validation
Validate before calling
if len(plain) > 0 {
p := int(plain[len(plain)-1])
if p == 0 || p > 16 || p > len(plain) {
return fmt.Errorf("invalid padding length %d — likely wrong key/IV", p)
}
} Try / catch
plain, err := DecryptURL(enc)
if err != nil {
if strings.Contains(err.Error(), "无效的填充长度") {
return refreshKeyAndRetry(enc) // reload current site key/IV
}
return err
} Prevention
- Verify key/IV currency whenever padding errors appear.
- Don't cache encrypted tokens across site key rotations.
- Pre-check the last plaintext byte looks like valid padding length (1..16).
- Confirm the upstream padding scheme before writing custom unpadding.
When it happens
Trigger: Decryption with mismatched AESKey/AESIV yields random-looking bytes whose last byte is an implausible padding length; ciphertext was corrupted in transit; input encrypted with a padding scheme other than PKCS7 (e.g. zero padding or no padding).
Common situations: SDSO site rotated keys so old constants decrypt to noise; cached encrypted URL from an older format; ciphertext passed through a transformation (URL decoding, charset conversion) that altered bytes.
Related errors
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/7878c06976e73ff6.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/sdso/sdso.go:437
if err != nil {
return "", fmt.Errorf("去除填充失败: %w", err)
}
return string(unpaddedText), nil
}
// removePKCS7Padding 去除PKCS7填充
func removePKCS7Padding(data []byte) ([]byte, error) {
if len(data) == 0 {
return nil, fmt.Errorf("数据为空")
}
// 获取填充长度
paddingLen := int(data[len(data)-1])
// 验证填充长度
if paddingLen == 0 || paddingLen > len(data) || paddingLen > aes.BlockSize {
return nil, fmt.Errorf("无效的填充长度: %d", paddingLen)
}
// 验证填充字节
for i := len(data) - paddingLen; i < len(data); i++ {
if data[i] != byte(paddingLen) {
return nil, fmt.Errorf("无效的填充字节")
}
}
// 返回去除填充后的数据
return data[:len(data)-paddingLen], nil
}
// cleanHTMLTags 清理HTML标签
func cleanHTMLTags(text string) string {
// 移除高亮标签 <span style="color: red;">...</span>
re := regexp.MustCompile(`<span[^>]*>(.*?)</span>`)
cleaned := re.ReplaceAllString(text, "$1")View on GitHub (pinned to beaa561337)