chenhg5/cc-connect · error

wecom-ws: invalid aeskey base64 length

Error message

wecom-ws: invalid aeskey base64 length

What it means

decodeWeComAESKey in platform/wecom/websocket_media.go validates the base64-encoded AES key supplied with WeCom websocket media URLs. It only accepts base64 strings whose length mod 4 leaves remainder 0, 2, or 3, appending the missing '=' padding itself; any other length (remainder 1, or absurdly long) cannot be valid padded base64, so it aborts. This guards against garbage keys before attempting a stdlib base64 decode.

Source

Thrown at platform/wecom/websocket_media.go:243

		}
		if len(key) != 32 {
			return nil, fmt.Errorf("wecom-ws: aeskey hex length %d, want 32 bytes", len(key))
		}
		return key, nil
	}

	// URL-safe alphabet → standard (RFC 4648 §5)
	s = strings.ReplaceAll(s, "-", "+")
	s = strings.ReplaceAll(s, "_", "/")

	switch len(s) % 4 {
	case 0:
	case 2:
		s += "=="
	case 3:
		s += "="
	default:
		return nil, fmt.Errorf("wecom-ws: invalid aeskey base64 length")
	}

	key, err := base64.StdEncoding.DecodeString(s)
	if err != nil {
		return nil, fmt.Errorf("wecom-ws: decode aeskey: %w", err)
	}
	if len(key) < 32 {
		return nil, fmt.Errorf("wecom-ws: aeskey decoded length %d, need >= 32", len(key))
	}
	return key, nil
}

func isHexString(s string) bool {
	for i := 0; i < len(s); i++ {
		c := s[i]
		switch {
		case c >= '0' && c <= '9', c >= 'a' && c <= 'f', c >= 'A' && c <= 'F':
		default:

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Check len(strings.TrimSpace(aesKey)) % 4 != 1 before calling; re-copy the EncodingAESKey from the WeCom admin console in full.
  2. If the key is hex-encoded, convert or pass it through the hex branch the tests cover (isHexString) rather than as base64.
  3. Normalize the key: strip whitespace, convert URL-safe '-_' to '+/' and re-pad with '=' to a multiple of 4 before decrypting.

Example fix

// before
raw := cfg.AESKey // e.g. truncated "abcde" (len 5)
plain, err := wecomDecryptFile(ciphertext, raw)
// after
raw := strings.TrimSpace(cfg.AESKey)
if len(raw)%4 == 1 {
    return nil, fmt.Errorf("bad aes key length %d", len(raw))
}
plain, err := wecomDecryptFile(ciphertext, raw)
Defensive patterns

Strategy: validation

Validate before calling

func validAESKeyLen(s string) bool {
    s = strings.TrimSpace(s)
    return len(s) > 0 && len(s)%4 != 1
}

Prevention

When it happens

Trigger: Calling wecomDecryptFile (via downloadWeComWSMedia) with an aesKeyB64 string whose length % 4 == 1, e.g. a truncated or corrupted base64 key, a hex string of odd length, or a key with stray characters removed/added.

Common situations: Copying the WeCom bot EncodingAESKey out of the admin console and clipping a character; a URL-safe, unpadded key passed through a transformation that stripped padding incorrectly; storing the key in config with whitespace/newline stripped unevenly; passing a hex-encoded key (64 hex chars is fine, 63 is not).

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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