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

  1. Parse the key with the adapter's parseAesKey helper, which accepts base64(raw 16) and base64(hex-ASCII 32) and returns exactly 16 bytes
  2. If you have a 32-char hex string, hex.DecodeString it to get 16 raw bytes before encrypting
  3. Check len(key)==16 before calling uploadBufferToCDN and regenerate/obtain the key from the CDN API if not
  4. 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

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


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