前言
网页版用的是 weapi,两个参数,RSA + AES-CBC:
随机生成一个AES密钥,用RSA公钥加密,为参数1;实际请求参数先用一个固定密钥AES加密一次,再用随机生成的AES密钥加密一次,为参数2
客户端(UWP/Win/Mac/Android)用的是 eapi,一个参数,AES-ECB:
固定的AES密钥,加密请求参数,部分返回数据也用同样的密钥加密过
Linux客户端用的是linux forward api,一个参数,AES-ECB:
固定的AES密钥,加密请求参数,返回数据都没有加密
三者里的固定AES密钥都不一样,eapi 的密钥是 e82ckenh8dichen8
加密 用 python 实现
安装 cryptography 库
1 pip install cryptography
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 import jsonfrom hashlib import md5from random import randrangefrom cryptography.hazmat.primitives import paddingfrom cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modesdef HexDigest (data ): return "" .join([hex (d)[2 :].zfill(2 ) for d in data]) def HashDigest (text ): HASH = md5(text.encode("utf-8" )) return HASH.digest() def HashHexDigest (text ): return HexDigest(HashDigest(text)) def eapi_encrypt (AES_KEY, url, payload ): digest = HashHexDigest(f"nobody{url} use{json.dumps(payload)} md5forencrypt" ) params = f"{url} -36cd479b6b5-{json.dumps(payload)} -36cd479b6b5-{digest} " padder = padding.PKCS7(algorithms.AES(AES_KEY).block_size).padder() padded_data = padder.update(params.encode()) + padder.finalize() cipher = Cipher(algorithms.AES(AES_KEY), modes.ECB()) encryptor = cipher.encryptor() enc = encryptor.update(padded_data) + encryptor.finalize() params = HexDigest(enc) return params url = "" url_param = "/api/playlist/update/playcount" AES_KEY = b"e82ckenh8dichen8" headers = { "Host" : "music.163.com" , "user-agent" : "NeteaseMusic/5.1.0.1523361492(116);Dalvik/2.1.0 (Linux; U; Android 14; Redmi K80 Pro Build/SKQ1.211006.001)" , "content-type" : "application/x-www-form-urlencoded" , "content-length" : "2823" , "accept-encoding" : "gzip" } payload = { "id" : "" , "header" : { "osver" : "14" , "deviceId" : "" , "appver" : "5.1.0" , "ntes_kaola_ad" : "1" , "versioncode" : "116" , "mobilename" : "RedmiK80Pro" , "buildver" : "1523361492" , "resolution" : "2400x1080" , "__csrf" : "" , "NMTID" : "" , "os" : "android" , "channel" : "google" , "MUSIC_A" : "" , "requestId" : str (randrange(20000000 , 30000000 )) }, "e_r" : "true" } cookies = { } params = eapi_encrypt(AES_KEY, url_param, payload) response = requests.post(url, headers=headers, data={"params" : params}, cookies=cookies) print (response.text)
解密 在线AES解密
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 def decrypt_aes_ecb (enc_data, key ): cipher = Cipher(algorithms.AES(key), modes.ECB()) decryptor = cipher.decryptor() decrypted_padded_data = decryptor.update(enc_data) + decryptor.finalize() unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder() unpadded_data = unpadder.update(decrypted_padded_data) + unpadder.finalize() return unpadded_data.decode('utf-8' ) response_daily = requests.post(url_daily, headers=headers, data={"params" : params_daily}, cookies=cookies) response_daily_decrypt = decrypt_aes_ecb(response_daily.content, AES_KEY) print (response_daily_decrypt)