chenhg5/cc-connect · error
wecom-ws: invalid pkcs7 pad length %d
Error message
wecom-ws: invalid pkcs7 pad length %d
What it means
pkcs7UnpadWeCom reads the last byte as the PKCS7 pad length and validates it is between 1 and 32 (WeCom uses up to 32-byte padding) and not longer than the data. If the final byte is 0 or >32 (or exceeds the buffer), the padding is structurally impossible and the data is corrupt — usually a wrong AES key produced garbage plaintext.
Source
Thrown at platform/wecom/websocket_media.go:299
block, err := aes.NewCipher(key32)
if err != nil {
return nil, err
}
if len(ciphertext)%aes.BlockSize != 0 {
return nil, fmt.Errorf("wecom-ws: ciphertext not multiple of block size")
}
plain := make([]byte, len(ciphertext))
cipher.NewCBCDecrypter(block, iv).CryptBlocks(plain, ciphertext)
return pkcs7UnpadWeCom(plain)
}
func pkcs7UnpadWeCom(data []byte) ([]byte, error) {
if len(data) == 0 {
return nil, fmt.Errorf("wecom-ws: empty padded data")
}
padLen := int(data[len(data)-1])
if padLen < 1 || padLen > 32 || padLen > len(data) {
return nil, fmt.Errorf("wecom-ws: invalid pkcs7 pad length %d", padLen)
}
for i := len(data) - padLen; i < len(data); i++ {
if int(data[i]) != padLen {
return nil, fmt.Errorf("wecom-ws: invalid pkcs7 padding")
}
}
return data[:len(data)-padLen], nil
}
func parseContentDispositionFilename(h string) string {
h = strings.TrimSpace(h)
if h == "" {
return ""
}
lower := strings.ToLower(h)
// RFC 5987: filename*=UTF-8''percent-encoded
if idx := strings.Index(lower, "filename*="); idx >= 0 {
val := strings.TrimSpace(h[idx+len("filename*="):])View on GitHub (pinned to 4000b2338a)
Solutions
- Verify the configured EncodingAESKey matches the bot that produced the media URL; re-sync after any key rotation.
- Treat this as a wrong-key symptom: if it occurs consistently, the key bytes are wrong even though base64 decoding succeeded.
- Confirm the media is WeCom AES-256-CBC with IV = first 16 key bytes (not a standard random-IV format).
Example fix
// before key := loadOldKey() // rotated in console plain, err := wecomDecryptFile(ct, key) // fails: invalid pkcs7 pad length // after key := loadKeyFromConsole() // re-fetched current EncodingAESKey plain, err := wecomDecryptFile(ct, key)
Defensive patterns
Strategy: try-catch
Validate before calling
k, err := base64.StdEncoding.DecodeString(key)
if err != nil || len(k) != 32 { /* fix config before runtime */ } Try / catch
plain, err := wecomDecryptFile(ct, key)
if err != nil && strings.Contains(err.Error(), "pkcs7") {
return fmt.Errorf("decryption failed — likely wrong EncodingAESKey for this bot: %w", err)
} Prevention
- Keep the EncodingAESKey in sync with the WeCom console; re-sync after rotation.
- Ensure the key used matches the bot that generated the media URL (multi-bot setups).
- Run a known-answer decryption test at startup.
When it happens
Trigger: wecomDecryptFile decrypts with a wrong/mismatched AES key; the last plaintext byte is then a random value (often 0x00 or >32) failing the pad-length sanity check.
Common situations: EncodingAESKey rotated in the WeCom console but stale key in config; decrypting media from a different bot than the one whose key was configured; key decoded with wrong padding earlier.
Understand the failure class
Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.
Related errors
- wecom-ws: empty padded data
- wecom-ws: invalid pkcs7 padding
- wecom-ws: invalid aeskey base64 length
- wecom-ws: decode aeskey: %w
- wecom-ws: aeskey decoded length %d, need >= 32
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/87bf7102c70b2472.
Report an issue: GitHub.