Archived
refactor: crypto 改用手写轮子的标准替代,去掉重复的函数内 import
- hex_digest:`"".join([hex(d)[2:].zfill(2) for d in data])` → `data.hex()`。 前者每字节做一次 hex()+zfill 再拼接,后者是 C 实现;两者输出相同。 - hash_hex_digest:绕道 digest() → hex_digest() 两步,直接 hexdigest()。 - _aes_encrypt / encrypt 里的函数内 import 删除:模块顶部已导入 Cipher/algorithms/modes/padding,函数内又导一遍纯属冗余; base64、secrets 则提到模块顶部(原来每次调用都要走一次 import 查找)。 - PKCS7(128) 保留字面量并加注释:**不要**改写成 algorithms.AES.block_size ——它在类型存根里声明为 property 而非 int,pyright 会报 reportArgumentType (本次实测踩到,门禁拦下)。 等价性验证:encrypt_params 对固定 payload 的输出 sha1 保持 76e3738f8eab61fcfd1145164ba8e1f91d40ee4f 不变;hex_digest/hash_hex_digest 的输出逐字符相同;并做了 docstring 逐条比对确认无文本误伤。
This commit is contained in:
1 parent
bd3a4ac70b
commit
d600b6a630
1 file changed
+10
-9
+10
-9
@@ -4,7 +4,9 @@
|
||||
(自 music_api.py 拆出,行为与原实现一致。)
|
||||
"""
|
||||
|
||||
import base64
|
||||
import json
|
||||
import secrets
|
||||
import urllib.parse
|
||||
from hashlib import md5
|
||||
from typing import Any
|
||||
@@ -22,7 +24,7 @@ class CryptoUtils:
|
||||
@staticmethod
|
||||
def hex_digest(data: bytes) -> str:
|
||||
"""将字节数据转换为十六进制字符串"""
|
||||
return "".join([hex(d)[2:].zfill(2) for d in data])
|
||||
return data.hex()
|
||||
|
||||
@staticmethod
|
||||
def hash_digest(text: str) -> bytes:
|
||||
@@ -32,7 +34,7 @@ class CryptoUtils:
|
||||
@staticmethod
|
||||
def hash_hex_digest(text: str) -> str:
|
||||
"""计算MD5哈希值并转换为十六进制字符串"""
|
||||
return CryptoUtils.hex_digest(CryptoUtils.hash_digest(text))
|
||||
return md5(text.encode("utf-8")).hexdigest()
|
||||
|
||||
@staticmethod
|
||||
def encrypt_params(url: str, payload: dict[str, Any]) -> str:
|
||||
@@ -66,9 +68,11 @@ class WeapiCrypto:
|
||||
|
||||
@staticmethod
|
||||
def _aes_encrypt(text: bytes, key: bytes) -> bytes:
|
||||
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
|
||||
from cryptography.hazmat.primitives.padding import PKCS7
|
||||
padder = PKCS7(128).padder()
|
||||
"""单层 AES-CBC + PKCS7 填充(密钥/IV 由官方 weapi 协议固定)。"""
|
||||
# PKCS7 以**比特**为单位:AES 分组固定 128 比特(=16 字节)。
|
||||
# 不要写 algorithms.AES.block_size——它在类型存根里声明为 property 而非 int,
|
||||
# pyright 会报 reportArgumentType。
|
||||
padder = padding.PKCS7(128).padder()
|
||||
padded = padder.update(text) + padder.finalize()
|
||||
cipher = Cipher(algorithms.AES(key), modes.CBC(WeapiCrypto.AES_IV))
|
||||
encryptor = cipher.encryptor()
|
||||
@@ -84,11 +88,8 @@ class WeapiCrypto:
|
||||
官方协议第二层加密的输入是第一层密文的
|
||||
**base64 字符串**(两次 AES 各自输出 base64)——93 条版本漏了中间那次
|
||||
base64,服务端解 params 第一层得到二进制、b64 解码必失败。"""
|
||||
import base64
|
||||
import secrets as _secrets
|
||||
|
||||
text = json.dumps(payload).encode("utf-8")
|
||||
secret_key = ''.join(_secrets.choice(WeapiCrypto.SEC_KEY_CHARSET) for _ in range(16))
|
||||
secret_key = ''.join(secrets.choice(WeapiCrypto.SEC_KEY_CHARSET) for _ in range(16))
|
||||
|
||||
first = base64.b64encode(
|
||||
WeapiCrypto._aes_encrypt(text, WeapiCrypto.AES_KEY)
|
||||
|
||||
Reference in new issue
Block a user