Files
musicdl-catalog-sync-suite/catalog-sync/musicdl/modules/utils/neteaseutils.py
T

86 lines
3.6 KiB
Python

'''
Function:
Implementation of NeteaseMusicClient Utils
Author:
Zhenchao Jin
WeChat Official Account (微信公众号):
Charles的皮卡丘
'''
import os
import json
import base64
import urllib
import codecs
import urllib.parse
from hashlib import md5
from Crypto.Cipher import AES
from cryptography.hazmat.primitives import padding
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
'''settings'''
MUSIC_QUALITIES = ['jymaster', 'dolby', 'sky', 'jyeffect', 'hires', 'lossless', 'exhigh', 'standard']
DEFAULT_COOKIES = {'MUSIC_U': '1eb9ce22024bb666e99b6743b2222f29ef64a9e88fda0fd5754714b900a5d70d993166e004087dd3b95085f6a85b059f5e9aba41e3f2646e3cebdbec0317df58c119e5'}
'''EapiCryptoUtils'''
class EapiCryptoUtils(object):
'''hexdigest'''
@staticmethod
def hexdigest(data: bytes):
return "".join([hex(d)[2:].zfill(2) for d in data])
'''hashdigest'''
@staticmethod
def hashdigest(text: str):
return md5(text.encode("utf-8")).digest()
'''hashhexdigest'''
@staticmethod
def hashhexdigest(text: str):
return EapiCryptoUtils.hexdigest(EapiCryptoUtils.hashdigest(text))
'''encryptparams'''
@staticmethod
def encryptparams(url: str, payload: dict, aes_key: bytes = b"e82ckenh8dichen8"):
url_path = urllib.parse.urlparse(url).path.replace("/eapi/", "/api/")
digest = EapiCryptoUtils.hashhexdigest(f"nobody{url_path}use{json.dumps(payload)}md5forencrypt")
params = f"{url_path}-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()
return EapiCryptoUtils.hexdigest(enc)
'''WeapiCryptoUtils'''
class WeapiCryptoUtils(object):
'''createsecretkey'''
@staticmethod
def createsecretkey(size: int):
return (''.join(map(lambda xx: (hex(ord(xx))[2:]), str(os.urandom(size)))))[0: 16]
'''aesencrypt'''
@staticmethod
def aesencrypt(string: str, sec_key: str):
pad = 16 - len(string) % 16
if isinstance(string, bytes): string = string.decode('utf-8')
string = string + str(pad * chr(pad))
sec_key = sec_key.encode('utf-8')
encryptor = AES.new(sec_key, 2, b'0102030405060708')
string = string.encode('utf-8')
ciphertext = encryptor.encrypt(string)
ciphertext = base64.b64encode(ciphertext)
return ciphertext
'''rsaencrypt'''
@staticmethod
def rsaencrypt(string: str, pub_key: str = '010001', modulus: str = '00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7'):
string = string[::-1]
rs = int(codecs.encode(string.encode('utf-8'), 'hex_codec'), 16) ** int(pub_key, 16) % int(modulus, 16)
return format(rs, 'x').zfill(256)
'''encryptparams'''
@staticmethod
def encryptparams(params: dict):
string = json.dumps(params)
sec_key = WeapiCryptoUtils.createsecretkey(16)
enc_string = WeapiCryptoUtils.aesencrypt(string=WeapiCryptoUtils.aesencrypt(string=string, sec_key='0CoJUm6Qyw8W8jud'), sec_key=sec_key)
enc_sec_key = WeapiCryptoUtils.rsaencrypt(string=sec_key)
post_data = {'params': enc_string, 'encSecKey': enc_sec_key}
return post_data