chenhg5/cc-connect · error

wecom-ws: invalid pkcs7 padding

Error message

wecom-ws: invalid pkcs7 padding

What it means

After the pad length passes range validation, pkcs7UnpadWeCom verifies that all padLen trailing bytes equal padLen (proper PKCS7 padding). If any byte differs, the padding is malformed — again almost always a symptom of decrypting with an incorrect AES key or corrupted ciphertext, producing random-looking trailing bytes.

Source

Thrown at platform/wecom/websocket_media.go:303

	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*="):])
		val = strings.TrimSuffix(strings.TrimSpace(val), ";")
		if after, ok := strings.CutPrefix(val, "UTF-8''"); ok {
			if dec, err := url.QueryUnescape(after); err == nil {
				return filepath.Base(dec)

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Confirm the EncodingAESKey belongs to the same bot/app that issued the media URL.
  2. Compare the SHA-256 of the downloaded ciphertext against the source (or re-download) to rule out transfer corruption.
  3. Sanity-check the rest of the plaintext: if it's entirely binary noise, the key is wrong; if only padding fails, suspect corruption.

Example fix

// before
sum := sha256.Sum256(raw)
// skip verification
plain, err := wecomDecryptFile(raw, key)
// after
if got := sha256.Sum256(raw); !bytes.Equal(got[:], expectedSum) {
    return nil, fmt.Errorf("ciphertext corrupted in transit")
}
plain, err := wecomDecryptFile(raw, key)
Defensive patterns

Strategy: retry

Validate before calling

if got := sha256.Sum256(raw); expectedSum != nil && !bytes.Equal(got[:], expectedSum) {
    return fmt.Errorf("ciphertext corrupted")
}

Try / catch

plain, err := wecomDecryptFile(raw, key)
if err != nil && strings.Contains(err.Error(), "invalid pkcs7 padding") {
    // re-download once with a fresh URL, then surface a wrong-key/corruption error
}

Prevention

When it happens

Trigger: wecomDecryptFile with wrong key or bit-flipped ciphertext; last byte happened to be a plausible 1–32 value but the remaining pad bytes don't match.

Common situations: Mixed-up keys between bots/environments; ciphertext truncated and re-padded by an intermediary; flaky storage corrupting the downloaded bytes.

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


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