chenhg5/cc-connect · error
invalid pkcs7 padding
Error message
invalid pkcs7 padding
What it means
After checking range and length, pkcs7Unpad verifies that the final n bytes all equal the pad byte value n; if any byte differs the buffer does not have valid PKCS7 padding and this error is returned. Because AES-ECB is deterministic, a padding mismatch after successful decryption almost always means the wrong key or wrong ciphertext — the data decrypted to something that is not validly padded plaintext.
Source
Thrown at platform/weixin/cdn.go:46
return ((plaintextLen + aes.BlockSize) / aes.BlockSize) * aes.BlockSize
}
func pkcs7Pad(b []byte, blockSize int) []byte {
if blockSize <= 0 || blockSize > 255 {
panic("invalid block size")
}
n := blockSize - (len(b) % blockSize)
pad := bytes.Repeat([]byte{byte(n)}, n)
return append(b, pad...)
}
func pkcs7Unpad(b []byte, blockSize int) ([]byte, error) {
if len(b) == 0 || len(b)%blockSize != 0 {
return nil, fmt.Errorf("invalid padded length %d", len(b))
}
n := int(b[len(b)-1])
if n == 0 || n > blockSize || n > len(b) {
return nil, fmt.Errorf("invalid pkcs7 padding")
}
for i := len(b) - n; i < len(b); i++ {
if b[i] != byte(n) {
return nil, fmt.Errorf("invalid pkcs7 padding")
}
}
return b[:len(b)-n], nil
}
func encryptAESECB(plaintext, key []byte) ([]byte, error) {
if len(key) != 16 {
return nil, fmt.Errorf("aes key must be 16 bytes, got %d", len(key))
}
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
padded := pkcs7Pad(plaintext, aes.BlockSize)View on GitHub (pinned to 4000b2338a)
Solutions
- Verify the aes_key belongs to this specific CDNMedia item (do not reuse keys across files)
- Re-download the media — the ciphertext may be corrupted or an error body
- Confirm the payload is actually AES-ECB-encrypted CDN data before decrypting
- Log the key hash and media URL to correlate key and file
Example fix
key, err := parseAesKey(media.AesKey, media.URL)
if err != nil { return err } // key tied to THIS media, not a cached/global key
plain, err := decryptAESECB(cipher, key)
if err != nil {
return fmt.Errorf("cdn: decrypt %s (key mismatch or corrupt file?): %w", media.URL, err)
} Defensive patterns
Strategy: validation
Validate before calling
key, err := parseAesKey(media.AesKey, media.URL)
if err != nil { return err }
// key now guaranteed to be the 16 bytes bound to this media item Try / catch
plain, err := decryptAESECB(cipher, key)
if err != nil {
if strings.Contains(err.Error(), "invalid pkcs7 padding") {
// wrong key or corrupt data — refetch key + media, don't reuse
return refreshKeyAndRedownload(media)
}
return err
} Prevention
- Bind each aes_key to its specific media item; never share keys across downloads
- Refetch media metadata if decryption fails — keys may have been rotated
- Do not attempt to use plaintext after a padding error (it is garbage)
- Verify expected file size/hash after decryption when available
When it happens
Trigger: Downloading WeChat CDN media with an aes_key that does not match the file; passing a key for a different media item; corrupted or truncated ciphertext that still happens to be block-aligned; decrypting data that was never PKCS7-padded (raw binary).
Common situations: Mixing up aes_key fields between concurrent CDN downloads; CDN returning an error page or HTML of exactly block-aligned length instead of the file; client/server key mismatch after re-upload.
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
- invalid padded length %d
- wecom-ws: empty padded data
- wecom-ws: invalid pkcs7 pad length %d
- wecom-ws: invalid pkcs7 padding
- aes key must be 16 bytes, got %d
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/e679edd05abe35c7.
Report an issue: GitHub.