chenhg5/cc-connect · error
aes key must be 16 bytes, got %d
Error message
aes key must be 16 bytes, got %d
What it means
encryptAESECB in the Weixin CDN uploader requires exactly a 16-byte (AES-128) key; any other length returns 'aes key must be 16 bytes, got %d'. The key comes from the WeChat Work CDN flow and must be exactly the AES-128 key the API expects. This is a pre-flight guard before aes.NewCipher so callers get a clear message instead of a crypto error.
Source
Thrown at platform/weixin/cdn.go:58
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)
out := make([]byte, len(padded))
for i := 0; i < len(padded); i += aes.BlockSize {
block.Encrypt(out[i:i+aes.BlockSize], padded[i:i+aes.BlockSize])
}
return out, nil
}
func decryptAESECB(ciphertext, key []byte) ([]byte, error) {
if len(key) != 16 {
return nil, fmt.Errorf("aes key must be 16 bytes, got %d", len(key))
}
if len(ciphertext)%aes.BlockSize != 0 {View on GitHub (pinned to 4000b2338a)
Solutions
- Parse the key with the adapter's parseAesKey helper, which accepts base64(raw 16) and base64(hex-ASCII 32) and returns exactly 16 bytes
- If you have a 32-char hex string, hex.DecodeString it to get 16 raw bytes before encrypting
- Check len(key)==16 before calling uploadBufferToCDN and regenerate/obtain the key from the CDN API if not
- Never pass hex/base64 text directly as the key bytes
Example fix
// before
key := []byte(media.AesKey) // still base64 text, wrong length
// after
key, err := parseAesKey(media.AesKey, media.URL)
if err != nil { return err }
enc, err := encryptAESECB(plaintext, key) // key is exactly 16 bytes Defensive patterns
Strategy: validation
Validate before calling
if len(key) != 16 {
return fmt.Errorf("upload: need 16-byte AES key, got %d", len(key))
}
enc, err := encryptAESECB(plaintext, key) Prevention
- Always derive the key via parseAesKey, never by hand-decoding base64
- Remember WeChat Work CDN uses AES-128: keys are exactly 16 raw bytes
- If the key is 32 hex chars, hex-decode to 16 bytes before use
- Add a unit test asserting len(key)==16 for your key-parsing path
When it happens
Trigger: Calling uploadBufferToCDN with a key decoded from a 24- or 32-byte base64 value (AES-192/256 key) or a raw hex string (32 ASCII chars = 32 bytes) instead of the 16 raw bytes; passing an empty/nil key; parsing aes_key incorrectly (not base64-decoding, or not unwrapping the hex-ASCII form).
Common situations: WeChat Work CDN aes_key arrives base64-encoded; if a developer decodes the hex-wrapped variant wrongly (keeps 32 hex chars) the key length check fires; config mistakes when hardcoding keys.
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
- wecom-ws: aeskey decoded length %d, need >= 32
- invalid padded length %d
- ciphertext length %d not aligned to block
- invalid pkcs7 padding
- %s: aes_key base64: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/9bcd2e76f4fdc55a.
Report an issue: GitHub.