chenhg5/cc-connect · error

invalid padded length %d

Error message

invalid padded length %d

What it means

pkcs7Unpad in the Weixin CDN helper validates that the buffer being unpadded is non-empty and an exact multiple of the AES block size (16). If the decrypted ciphertext has a padded length that fails this check, it returns 'invalid padded length %d' with the actual byte count. This means the input to unpad was not a valid block-aligned PKCS7 buffer, so decryption produced garbage or was truncated.

Source

Thrown at platform/weixin/cdn.go:42

func aesECBPaddedSize(plaintextLen int) int {
	if plaintextLen < 0 {
		return 0
	}
	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)

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Verify the downloaded ciphertext is complete (compare against the expected file size) before decrypting
  2. Re-download the CDN media; do not call pkcs7Unpad directly on unencrypted data
  3. Check that decryptAESECB received the full, block-aligned buffer

Example fix

// before
data, _ := io.ReadAll(resp.Body)
plain, err := decryptAESECB(data, key)
// after
data, _ := io.ReadAll(resp.Body)
if len(data) == 0 || len(data)%16 != 0 {
    return nil, fmt.Errorf("cdn: incomplete download, got %d bytes", len(data))
}
plain, err := decryptAESECB(data, key)
Defensive patterns

Strategy: validation

Validate before calling

if len(cipher) == 0 || len(cipher)%aes.BlockSize != 0 {
    return fmt.Errorf("cdn: bad ciphertext length %d", len(cipher))
}
plain, err := decryptAESECB(cipher, key)

Try / catch

plain, err := decryptAESECB(data, key)
if err != nil {
    if strings.Contains(err.Error(), "invalid padded length") {
        return redownloadAndDecrypt(media) // truncated payload
    }
    return err
}

Prevention

When it happens

Trigger: decryptAESECB called with a ciphertext whose length is not a multiple of 16 (the length check precedes it, so this fires mainly for len==0 or when unpad is called directly on non-aligned data); truncated CDN download where the tail bytes are missing; calling pkcs7Unpad on an empty slice.

Common situations: Interrupted/partial WeChat CDN file download before AES decryption; version change in CDN payload framing; misuse of the helper on raw (unencrypted) bytes.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/4dbb913a04789964. Report an issue: GitHub.