1. 逆向目标与核心参数解析网易云音乐作为国内主流音乐平台其API接口采用了多重加密机制保护数据安全。当我们尝试通过程序调用其歌曲播放接口时会遇到三个关键加密参数csrf_token、params和encSecKey。其中params和encSecKey的加密逻辑最为复杂涉及AES和RSA两种加密算法。实际抓包会发现请求歌曲播放接口如/weapi/song/enhance/player/url/v1时必须携带这三个加密参数。以获取歌曲《起风了》为例ID1330348068原始请求数据经过加密后变成类似这样的形式{ params: C9F975B2A3E...长达数百字符的密文, encSecKey: 6A1D8E2F4B0...固定长度的RSA密文 }2. 逆向分析实战步骤2.1 加密入口定位技巧在Chrome开发者工具中推荐使用以下三种方式快速定位加密函数XHR断点法在Sources面板的XHR Breakpoints中添加/weapi/接口路径关键字搜索法全局搜索encSecKey或params等关键词调用栈追踪法在Network面板找到目标请求查看Initiator调用栈通过调试会发现核心加密发生在window.asrsea()函数中。这个函数接收四个参数window.asrsea(JSON.stringify(requestData), pubKey, modulus, secretKey)2.2 csrf_token生成机制csrf_token的获取相对简单它直接取自用户Cookie中的__csrf值。通过以下JS代码即可提取function getCsrfToken() { const cookieStr document.cookie; const match cookieStr.match(/\b__csrf([^;])/); return match ? match[1] : ; }在Python中可以通过requests库自动维护cookiesession requests.Session() response session.get(https://music.163.com) csrf_token session.cookies.get(__csrf)3. 核心加密算法解析3.1 AES加密流程params生成params参数经过两次AES加密第一次使用固定密钥0CoJUm6Qyw8W8jud加密原始JSON数据第二次使用随机生成的16位密钥加密第一次的结果关键加密代码如下function aesEncrypt(text, key) { const iv CryptoJS.enc.Utf8.parse(0102030405060708); const encrypted CryptoJS.AES.encrypt( CryptoJS.enc.Utf8.parse(text), CryptoJS.enc.Utf8.parse(key), { iv: iv, mode: CryptoJS.mode.CBC } ); return encrypted.toString(); }3.2 RSA加密流程encSecKey生成encSecKey是对AES随机密钥的RSA加密使用以下固定公钥模数modulus00e0b509f6259df8...长达256位的十六进制字符串指数exponent010001特别需要注意的是网易云在RSA加密前会对明文进行字节逆序处理。Python实现时需要特别注意from Crypto.PublicKey import RSA from Crypto.Cipher import PKCS1_v1_5 def rsa_encrypt(text, modulus, exponent): # 字节逆序处理 text text[::-1] # 标准RSA加密流程 key RSA.construct((int(modulus, 16), int(exponent, 16))) cipher PKCS1_v1_5.new(key) return cipher.encrypt(text.encode()).hex()4. Python完整实现方案4.1 加密函数封装结合上述分析完整的Python实现如下import json import requests from Crypto.Cipher import AES, PKCS1_v1_5 from Crypto.Util.Padding import pad from Crypto.PublicKey import RSA import binascii class NeteaseCrypto: def __init__(self): self.aes_key 0CoJUm6Qyw8W8jud self.aes_iv 0102030405060708 self.rsa_modulus 00e0b509f...完整modulus self.rsa_exponent 010001 def aes_encrypt(self, text, key): cipher AES.new(key.encode(), AES.MODE_CBC, self.aes_iv.encode()) padded pad(text.encode(), AES.block_size) return binascii.b2a_hex(cipher.encrypt(padded)).decode() def rsa_encrypt(self, text): text text[::-1] # 关键逆序步骤 key RSA.construct((int(self.rsa_modulus, 16), int(self.rsa_exponent, 16))) cipher PKCS1_v1_5.new(key) return cipher.encrypt(text.encode()).hex() def generate_params(self, data): text json.dumps(data) random_key abcdefghijklmnop # 可固定或随机生成 params self.aes_encrypt(text, self.aes_key) params self.aes_encrypt(params, random_key) enc_seckey self.rsa_encrypt(random_key) return params, enc_seckey4.2 实战请求示例获取歌曲播放地址的完整流程crypto NeteaseCrypto() session requests.Session() # 获取csrf_token session.get(https://music.163.com) csrf_token session.cookies.get(__csrf) # 构造请求数据 request_data { ids: [1330348068], # 歌曲ID level: standard, encodeType: aac, csrf_token: csrf_token } # 生成加密参数 params, encSecKey crypto.generate_params(request_data) # 发送请求 response session.post( https://music.163.com/weapi/song/enhance/player/url/v1, data{params: params, encSecKey: encSecKey} ) print(response.json())5. 常见问题与解决方案5.1 加密结果验证失败可能原因及解决方法AES填充问题确保使用PKCS7填充模式RSA密钥格式modulus需要完整包含00e0b...前缀字节序问题确认在RSA加密前进行了字符串逆序5.2 高频请求限制建议采取以下策略合理设置请求间隔建议≥2秒使用代理IP轮询复用session保持cookie有效性5.3 音质参数调整通过修改请求数据中的level字段可以获取不同音质standard标准音质higher较高音质exhigh极高音质lossless无损音质需VIP6. 技术原理深度剖析6.1 网易云的安全设计思路这种加密方案结合了对称加密AES高效加密业务数据非对称加密RSA安全传输AES密钥随机数防御每次请求使用不同的AES密钥客户端验证csrf_token防止CSRF攻击6.2 加密流程优化建议在实际项目中可以预编译加密函数提升性能缓存RSA密钥对象避免重复构造使用Cython加速加密计算# 性能优化示例 import functools functools.lru_cache(maxsize10) def get_rsa_cipher(): key RSA.construct((int(modulus, 16), int(exponent, 16))) return PKCS1_v1_5.new(key)7. 扩展应用场景掌握该技术后可以实现歌曲元数据采集需注意版权限制个性化推荐分析歌单同步工具音质批量检测工具特别提醒所有技术方案应遵守网易云音乐的API使用条款建议仅用于学习研究和合规场景。在实际开发中我通常会设置严格的请求频率限制并添加详细的日志记录以便问题排查。
【JS逆向】网易云音乐加密参数params与encSecKey的逆向分析与实战
1. 逆向目标与核心参数解析网易云音乐作为国内主流音乐平台其API接口采用了多重加密机制保护数据安全。当我们尝试通过程序调用其歌曲播放接口时会遇到三个关键加密参数csrf_token、params和encSecKey。其中params和encSecKey的加密逻辑最为复杂涉及AES和RSA两种加密算法。实际抓包会发现请求歌曲播放接口如/weapi/song/enhance/player/url/v1时必须携带这三个加密参数。以获取歌曲《起风了》为例ID1330348068原始请求数据经过加密后变成类似这样的形式{ params: C9F975B2A3E...长达数百字符的密文, encSecKey: 6A1D8E2F4B0...固定长度的RSA密文 }2. 逆向分析实战步骤2.1 加密入口定位技巧在Chrome开发者工具中推荐使用以下三种方式快速定位加密函数XHR断点法在Sources面板的XHR Breakpoints中添加/weapi/接口路径关键字搜索法全局搜索encSecKey或params等关键词调用栈追踪法在Network面板找到目标请求查看Initiator调用栈通过调试会发现核心加密发生在window.asrsea()函数中。这个函数接收四个参数window.asrsea(JSON.stringify(requestData), pubKey, modulus, secretKey)2.2 csrf_token生成机制csrf_token的获取相对简单它直接取自用户Cookie中的__csrf值。通过以下JS代码即可提取function getCsrfToken() { const cookieStr document.cookie; const match cookieStr.match(/\b__csrf([^;])/); return match ? match[1] : ; }在Python中可以通过requests库自动维护cookiesession requests.Session() response session.get(https://music.163.com) csrf_token session.cookies.get(__csrf)3. 核心加密算法解析3.1 AES加密流程params生成params参数经过两次AES加密第一次使用固定密钥0CoJUm6Qyw8W8jud加密原始JSON数据第二次使用随机生成的16位密钥加密第一次的结果关键加密代码如下function aesEncrypt(text, key) { const iv CryptoJS.enc.Utf8.parse(0102030405060708); const encrypted CryptoJS.AES.encrypt( CryptoJS.enc.Utf8.parse(text), CryptoJS.enc.Utf8.parse(key), { iv: iv, mode: CryptoJS.mode.CBC } ); return encrypted.toString(); }3.2 RSA加密流程encSecKey生成encSecKey是对AES随机密钥的RSA加密使用以下固定公钥模数modulus00e0b509f6259df8...长达256位的十六进制字符串指数exponent010001特别需要注意的是网易云在RSA加密前会对明文进行字节逆序处理。Python实现时需要特别注意from Crypto.PublicKey import RSA from Crypto.Cipher import PKCS1_v1_5 def rsa_encrypt(text, modulus, exponent): # 字节逆序处理 text text[::-1] # 标准RSA加密流程 key RSA.construct((int(modulus, 16), int(exponent, 16))) cipher PKCS1_v1_5.new(key) return cipher.encrypt(text.encode()).hex()4. Python完整实现方案4.1 加密函数封装结合上述分析完整的Python实现如下import json import requests from Crypto.Cipher import AES, PKCS1_v1_5 from Crypto.Util.Padding import pad from Crypto.PublicKey import RSA import binascii class NeteaseCrypto: def __init__(self): self.aes_key 0CoJUm6Qyw8W8jud self.aes_iv 0102030405060708 self.rsa_modulus 00e0b509f...完整modulus self.rsa_exponent 010001 def aes_encrypt(self, text, key): cipher AES.new(key.encode(), AES.MODE_CBC, self.aes_iv.encode()) padded pad(text.encode(), AES.block_size) return binascii.b2a_hex(cipher.encrypt(padded)).decode() def rsa_encrypt(self, text): text text[::-1] # 关键逆序步骤 key RSA.construct((int(self.rsa_modulus, 16), int(self.rsa_exponent, 16))) cipher PKCS1_v1_5.new(key) return cipher.encrypt(text.encode()).hex() def generate_params(self, data): text json.dumps(data) random_key abcdefghijklmnop # 可固定或随机生成 params self.aes_encrypt(text, self.aes_key) params self.aes_encrypt(params, random_key) enc_seckey self.rsa_encrypt(random_key) return params, enc_seckey4.2 实战请求示例获取歌曲播放地址的完整流程crypto NeteaseCrypto() session requests.Session() # 获取csrf_token session.get(https://music.163.com) csrf_token session.cookies.get(__csrf) # 构造请求数据 request_data { ids: [1330348068], # 歌曲ID level: standard, encodeType: aac, csrf_token: csrf_token } # 生成加密参数 params, encSecKey crypto.generate_params(request_data) # 发送请求 response session.post( https://music.163.com/weapi/song/enhance/player/url/v1, data{params: params, encSecKey: encSecKey} ) print(response.json())5. 常见问题与解决方案5.1 加密结果验证失败可能原因及解决方法AES填充问题确保使用PKCS7填充模式RSA密钥格式modulus需要完整包含00e0b...前缀字节序问题确认在RSA加密前进行了字符串逆序5.2 高频请求限制建议采取以下策略合理设置请求间隔建议≥2秒使用代理IP轮询复用session保持cookie有效性5.3 音质参数调整通过修改请求数据中的level字段可以获取不同音质standard标准音质higher较高音质exhigh极高音质lossless无损音质需VIP6. 技术原理深度剖析6.1 网易云的安全设计思路这种加密方案结合了对称加密AES高效加密业务数据非对称加密RSA安全传输AES密钥随机数防御每次请求使用不同的AES密钥客户端验证csrf_token防止CSRF攻击6.2 加密流程优化建议在实际项目中可以预编译加密函数提升性能缓存RSA密钥对象避免重复构造使用Cython加速加密计算# 性能优化示例 import functools functools.lru_cache(maxsize10) def get_rsa_cipher(): key RSA.construct((int(modulus, 16), int(exponent, 16))) return PKCS1_v1_5.new(key)7. 扩展应用场景掌握该技术后可以实现歌曲元数据采集需注意版权限制个性化推荐分析歌单同步工具音质批量检测工具特别提醒所有技术方案应遵守网易云音乐的API使用条款建议仅用于学习研究和合规场景。在实际开发中我通常会设置严格的请求频率限制并添加详细的日志记录以便问题排查。