{"record":{"id":"503454037787dc52","repo":"chenhg5/cc-connect","slug":"wecom-ws-aeskey-decoded-length-d-need-32","errorCode":null,"errorMessage":"wecom-ws: aeskey decoded length %d, need >= 32","messagePattern":"wecom-ws: aeskey decoded length (.+?), need >= 32","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/wecom/websocket_media.go","lineNumber":251,"sourceCode":"\ts = strings.ReplaceAll(s, \"-\", \"+\")\n\ts = strings.ReplaceAll(s, \"_\", \"/\")\n\n\tswitch len(s) % 4 {\n\tcase 0:\n\tcase 2:\n\t\ts += \"==\"\n\tcase 3:\n\t\ts += \"=\"\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"wecom-ws: invalid aeskey base64 length\")\n\t}\n\n\tkey, err := base64.StdEncoding.DecodeString(s)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"wecom-ws: decode aeskey: %w\", err)\n\t}\n\tif len(key) < 32 {\n\t\treturn nil, fmt.Errorf(\"wecom-ws: aeskey decoded length %d, need >= 32\", len(key))\n\t}\n\treturn key, nil\n}\n\nfunc isHexString(s string) bool {\n\tfor i := 0; i < len(s); i++ {\n\t\tc := s[i]\n\t\tswitch {\n\t\tcase c >= '0' && c <= '9', c >= 'a' && c <= 'f', c >= 'A' && c <= 'F':\n\t\tdefault:\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\n// wecomDecryptFile decrypts payload from WeCom WS media URLs (AES-256-CBC, IV = first 16 key bytes).\n// Same algorithm as @wecom/aibot-node-sdk decryptFile.","sourceCodeStart":233,"sourceCodeEnd":269,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/wecom/websocket_media.go#L233-L269","documentation":"decodeWeComAESKey decodes successfully but the resulting byte slice is shorter than 32 bytes, which cannot serve as an AES-256 key. wecomDecryptFile slices key[:32], so a short key would panic; this check converts that into a descriptive error reporting the actual decoded length.","triggerScenarios":"Passing a base64 string that decodes to <32 bytes — e.g. a 16-byte AES-128 key, an auth token mistakenly used as the media AES key, or a partially pasted EncodingAESKey.","commonSituations":"Confusing the WeCom callback EncodingAESKey (43 chars, 32 bytes) with a shorter token or Secret; truncation by spreadsheet/config tooling; using a key generated for a different SDK.","solutions":["Verify the key is the full EncodingAESKey (43 unpatched base64 chars → 32 bytes) from the WeCom bot settings.","Compute base64.StdEncoding.DecodeString offline and check len(key) == 32 before deploying the config.","If your deployment genuinely uses a 16-byte key, this code path expects AES-256; regenerate/configure a 32-byte key."],"exampleFix":"// before\nkey := cfg.Token // wrong field, decodes to ~16 bytes\n// after\nkey := cfg.EncodingAESKey // 43-char base64 -> 32 bytes\nif k, err := base64.StdEncoding.DecodeString(key); err != nil || len(k) < 32 {\n    return fmt.Errorf(\"aes key must decode to >=32 bytes\")\n}","handlingStrategy":"validation","validationCode":"func isAES256Key(b64 string) bool {\n    k, err := base64.StdEncoding.DecodeString(strings.TrimSpace(b64))\n    return err == nil && len(k) >= 32\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use the EncodingAESKey field, not token/secret, when configuring the bot.","Check decoded length == 32 in a startup self-test.","Re-copy the key after any WeCom console rotation."],"tags":["wecom","crypto","aes","key-length"],"backgroundTag":"invalid-argument-value","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}