{"record":{"id":"c62f78f7b4116e29","repo":"AlistGo/alist","slug":"step3-response-layer2-aes-ecb-decrypt-failed-w","errorCode":null,"errorMessage":"step3 response layer2 aes ecb decrypt failed: %w","messagePattern":"step3 response layer2 aes ecb decrypt failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/139/util.go","lineNumber":1227,"sourceCode":"\t}\n\n\thexInner := jsoniter.Get(decryptedLayer1StrBytes, \"data\").ToString()\n\tif hexInner == \"\" {\n\t\treturn \"\", errors.New(\"missing data field in first layer decryption result\")\n\t}\n\tlog.Debugf(\"DEBUG: 第一层解密提取到 hex_inner, length=%d\", len(hexInner))\n\n\tkey2, err := hex.DecodeString(KEY_HEX_2)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to decode KEY_HEX_2: %w\", err)\n\t}\n\thexInnerBytes, err := hex.DecodeString(hexInner)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to decode hex_inner: %w\", err)\n\t}\n\tfinalJsonStrBytes, err := aesEcbDecrypt(hexInnerBytes, key2)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"step3 response layer2 aes ecb decrypt failed: %w\", err)\n\t}\n\tlog.Debugf(\"DEBUG: third party login response decrypted.\")\n\n\tauthToken := jsoniter.Get(finalJsonStrBytes, \"authToken\").ToString()\n\tif authToken == \"\" {\n\t\treturn \"\", errors.New(\"failed to extract authToken from final decryption result\")\n\t}\n\n\taccount := jsoniter.Get(finalJsonStrBytes, \"account\").ToString()\n\tuserDomainId := jsoniter.Get(finalJsonStrBytes, \"userDomainId\").ToString()\n\tif account == \"\" || userDomainId == \"\" {\n\t\treturn \"\", errors.New(\"failed to extract account or userDomainId from final decryption result\")\n\t}\n\n\td.Account = account\n\td.UserDomainID = userDomainId\n\treturn base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf(\"pc:%s:%s\", account, authToken))), nil\n}","sourceCodeStart":1209,"sourceCodeEnd":1245,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/drivers/139/util.go#L1209-L1245","documentation":"The second decryption layer of the SSO response failed: the hex-decoded bytes could not be decrypted with AES-ECB using KEY_HEX_2. The ciphertext was not produced with the expected static key — a strong signal the server-side protocol/keys changed or the payload is an error blob.","triggerScenarios":"aesEcbDecrypt rejects the data (bad block size or unpadding failure) after hexInner decoded fine; typically after China Mobile rotates keys or alters the layer-2 scheme in a newer app build.","commonSituations":"OpenList driver version lagging behind a 139 cloud app update (keys/headers captured from old app builds), or an upstream error body accidentally passing earlier checks.","solutions":["Update OpenList to the newest release — key constants (KEY_HEX_1/KEY_HEX_2) and headers are re-captured when the app protocol changes","Re-capture the traffic from the current official android client and update KEY_HEX_2 in a local fork if you cannot wait upstream","Verify the whole flow with fresh cookies to rule out error payloads masquerading as ciphertext","Report upstream with the failing step and app version if persistent"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Pre-check ciphertext block alignment before ECB decrypt\nif len(hexInnerBytes) == 0 || len(hexInnerBytes)%aes.BlockSize != 0 {\n\treturn fmt.Errorf(\"layer2 ciphertext misaligned (%d bytes): protocol drift\", len(hexInnerBytes))\n}","typeGuard":"func isLayer2DecryptErr(err error) bool {\n\treturn err != nil && strings.Contains(err.Error(), \"layer2 aes ecb decrypt failed\")\n}","tryCatchPattern":"// Never auto-retry; refresh keys or update the driver\nif isLayer2DecryptErr(err) {\n\treturn fmt.Errorf(\"139 SSO keys outdated — update OpenList or re-capture KEY_HEX_2: %w\", err)\n}","preventionTips":["Subscribe to OpenList releases; key rotations are patched upstream quickly","When self-capturing keys, record the android app version alongside KEY_HEX_1/2","Treat ECB-decrypt failures as hard protocol errors, not transient ones"],"tags":["crypto","aes","protocol","version-drift"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}