Tencent/WeKnora · error

aes key too short: %d bytes

Error message

aes key too short: %d bytes

What it means

decryptAESCBC rejects AES keys shorter than 16 bytes because Go's crypto/aes only supports 16-, 24-, or 32-byte keys. The WeCom aeskey is expected to be base64 of a 16-byte (AES-128) key; fewer bytes means the key was decoded wrong or truncated.

Source

Thrown at internal/im/wecom/ws_adapter.go:143

	return io.NopCloser(bytes.NewReader(decrypted)), fileName, nil
}

// decryptAESCBC decrypts data encrypted with AES-256-CBC using PKCS#7 padding.
// The aesKeyB64 is the base64-encoded AES key provided per-message by WeCom.
// IV is the first 16 bytes of the decoded AES key.
func decryptAESCBC(ciphertext []byte, aesKeyB64 string) ([]byte, error) {
	// WeCom's per-message aeskey is base64-encoded (43 chars → 32 bytes after decode)
	aesKey, err := base64.StdEncoding.DecodeString(aesKeyB64 + "=")
	if err != nil {
		// Try without padding
		aesKey, err = base64.RawStdEncoding.DecodeString(aesKeyB64)
		if err != nil {
			return nil, fmt.Errorf("base64 decode aes key: %w", err)
		}
	}

	if len(aesKey) < 16 {
		return nil, fmt.Errorf("aes key too short: %d bytes", len(aesKey))
	}

	block, err := aes.NewCipher(aesKey)
	if err != nil {
		return nil, fmt.Errorf("new aes cipher: %w", err)
	}

	if len(ciphertext) < aes.BlockSize {
		return nil, fmt.Errorf("ciphertext too short: %d bytes", len(ciphertext))
	}
	if len(ciphertext)%aes.BlockSize != 0 {
		return nil, fmt.Errorf("ciphertext not a multiple of block size: %d bytes", len(ciphertext))
	}

	// IV = first 16 bytes of the AES key
	iv := aesKey[:aes.BlockSize]
	mode := cipher.NewCBCDecrypter(block, iv)
	plaintext := make([]byte, len(ciphertext))

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Verify the message's aeskey is valid base64 decoding to exactly 16 bytes; re-read it from the original message.
  2. Check that decryptAESCBC actually base64-decodes the key before the length check (the error prints the decoded length).
  3. Never truncate or trim the key string when storing/parsing messages.
  4. If the key is genuinely short, the message is corrupt — re-fetch the message from WeCom.

Example fix

// before
key, _ := base64.StdEncoding.DecodeString(strings.TrimSpace(msg.AesKey))
// after
key, err := base64.StdEncoding.DecodeString(msg.AesKey)
if err != nil || len(key) != 16 {
    return fmt.Errorf("invalid aes key: decoded %d bytes", len(key))
}
Defensive patterns

Strategy: validation

Validate before calling

decoded, err := base64.StdEncoding.DecodeString(msg.AesKey)
if err != nil || len(decoded) < 16 {
    return fmt.Errorf("refusing to decrypt: aes key decodes to %d bytes", len(decoded))
}

Type guard

func isUsableAESKey(key []byte) bool {
    return len(key) == 16 || len(key) == 24 || len(key) == 32
}

Try / catch

rc, name, err := adapter.DownloadFile(ctx, msg)
if err != nil && strings.Contains(err.Error(), "aes key too short") {
    // corrupt/mis-parsed message: re-fetch or skip
}

Prevention

When it happens

Trigger: Calling decryptAESCBC (via DownloadFile) with an aesKey that decodes to fewer than 16 bytes — e.g. malformed base64 handled by a path that didn't error, a truncated key string, or passing the base64 string raw instead of decoded bytes.

Common situations: Manually trimmed/padded key stored in config; passing the base64-encoded key literally as the key bytes; WeCom SDK or message format change altering the aeskey field; copy/paste dropping characters.

Related errors


AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02). Data as JSON: /api/errors/c49a57561b7f0cd9. Report an issue: GitHub.