包含关键字 b9 的文章 - 空痕博客 - 编程学习分享
首页
小记
php
python
uniapp
前端
其他
机器人
QQ机器人
项目
功能库
应用
其他页面
友情链接
用户留言
联系空痕
热门文章
PHP搭建QQ机器人(QQ官方)
解决三个导致 Google Antigravity 无法登录的问题
移动云盘分享的链接信息获取接口请求体/响应体加密及解密
下载文件到指定文件夹
上传文件到夸克网盘python代码
标签搜索
uniapp
python
PHP
UTS
uniapp-x
模板
html
VUE
夸克网盘
移动云盘
APP
KongHen
机器人
QQ
ID3
pyinstaller
redis
Echarts
邮箱
js
发布
登录
注册
找到
2
篇与
b9
相关的结果
2025-11-26
移动云盘分享的链接信息获取接口请求体/响应体加密及解密
实现目的 有没有过这样的体验?手里攥着几十上百个网盘分享链接,要一个个点进页面、手动确认转存到自己的网盘——重复的操作像流水线作业,不仅浪费时间,而且还可能会漏掉文件。所以搞个自动转存脚本是非常有必要的。 打开分享链接->点击F12->查看网络,$[阿鲁表情]::(哭泣) 网盘的分享链接数据居然全是加密的。观察了一下加密字符好像是base64,直接一手解码,乱码!!!作为一个对逆向工程一窍不通的开发者,这已经超出了我的能力范围。 既然自己搞不定,不如试试“AI”。刚好试试最近热门的Gork.我把收集到的几条请求体、响应体密文整理好,清晰标注了获取场景,然后一股脑发给了Gork。 让我惊喜的是,Gork不仅精准识别出这些密文来自哪个网盘站点,还直接给出了对应的加密算法类型。我拿着密钥代入算法解密,结果发现解密失败$[阿鲁表情]::(中指)。 我只能继续问Gork,让它提供判断加密算法和密钥的参考来源。好在Gork很配合,直接给出了几个链接,包含GitHub及CSDN的链接。将几个站点都查看了一遍,选择了最简单的,文件名清晰且代码精简。 经过测试,解密可以使用,但是加密报错。将问题再扔给Gork,修复了即便终于给了我可以使用的代码,自己再整合一下就完成了转存分享中最难的部分$[阿鲁表情]::(得意)。 演示链接 链接: https://yun.139.com/shareweb/#/w/i/2qidG1XEkUKi0 提取码:d78q 复制内容打开中国移动云盘手机APP,操作更方便哦 解密解密分析 项目说明算法AES-128-CBC + PKCS7 填充密钥"PVGDwmcvfs1uV3d1"(UTF-8 编码)IV随机,前 16 字节拼接在密文前密文Base64 解码后第 17 字节起编码整体 Base64(标准,无 URL-safe)加解密代码 需要安装crypto-js库 const CryptoJS = require("crypto-js"); // 新版外链接口固定密钥 const FIXED_KEY = "PVGDwmcvfs1uV3d1"; /** * 移动云盘新版外链加密(OutLink) * @param {string} plaintextJson 明文JSON字符串 * @returns {string} 最终的Base64密文(和官方App一模一样) */ function encryptOutLink(plaintextJson) { // 1. 生成随机IV(16字节) const iv = CryptoJS.lib.WordArray.random(16); // 2. AES-128-CBC 加密 const encrypted = CryptoJS.AES.encrypt( plaintextJson, CryptoJS.enc.Utf8.parse(FIXED_KEY), { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 } ); // 3. 把 IV(16字节) + 密文 拼接起来 const ivAndCiphertext = iv.concat(encrypted.ciphertext); // 4. 整体转Base64 → 这就是最终发出去的字符串 return ivAndCiphertext.toString(CryptoJS.enc.Base64); } /** * 解密移动云盘新版外链(OutLink) * @param {string} encryptedBase64 响应体的 Base64 字符串(可能带空格) * @returns {string} 解密后的明文 JSON */ function decryptOutLink(encryptedBase64) { try { // 1. 清理 Base64 const cleanB64 = encryptedBase64.replace(/\s+/g, '');; // 2. Base64 解码 → WordArray const combined = CryptoJS.enc.Base64.parse(cleanB64); const totalLength = combined.sigBytes; // 总字节数 // 3. 提取 IV(前 16 字节 = 4 words)和密文(剩余) const ivBytes = combined.sigBytes / 4; // 每个 word 4 字节 const iv = CryptoJS.lib.WordArray.create(combined.words.slice(0, 4)); // 前 16 字节 const ciphertext = CryptoJS.lib.WordArray.create( combined.words.slice(4), totalLength - 16 // 剩余长度 ); // 4. AES-128-CBC 解密 const decrypted = CryptoJS.AES.decrypt( { ciphertext: ciphertext }, CryptoJS.enc.Utf8.parse(FIXED_KEY), { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 } ); // 5. 转 UTF-8 字符串(JSON) const plaintext = decrypted.toString(CryptoJS.enc.Utf8); if (!plaintext) { throw new Error("解密为空,可能是填充错误或密钥不对"); } return plaintext; } catch (error) { throw new Error(`解密失败: ${error.message}`); } } // 测试 // getOutLinkGeneral 请求体加密 const test1 = JSON.stringify({ getOutLinkGeneralReq: { linkID: "2qidFfUiXYAas", isPasswd: 1 } }); const res1 = encryptOutLink(test1); console.log("getOutLinkGeneral 请求体加密结果:", res1); console.log("getOutLinkGeneral 请求体解密结果:", decryptOutLink(res1)); // getOutLinkInfoV6 请求体加密 const test2 = JSON.stringify({ getOutLinkInfoReq: { account: "", linkID: "2qidG1XEkUKi0", passwd: "d78q", caSrt: 0, coSrt: 0, srtDr: 1, bNum: 1, pCaID: "root", eNum: 200 } }); const res2 = encryptOutLink(test2); console.log("getOutLinkInfoV6 请求体加密结果:", res2); console.log("getOutLinkInfoV6 请求体解密结果:", decryptOutLink(res2)); // getOutLinkGeneral 响应体解密 const test3 = `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`; const res3 = decryptOutLink(test3); console.log("getOutLinkGeneral 响应体解密结果:", res3); console.log("getOutLinkGeneral 响应体加密结果:", encryptOutLink(res3)); // getOutLinkInfoV6 响应体解密 const text4 = "q1FepUXZdRCJESkrGVyAkMsyT+9 NJNaPxqtbSHUvoMsRyKS2Ju2Ed8nQR/XmD9c1hlRRRpMtR++bsEbNRKL6Z9dvrqioStjUN3Cfi41ANo8YDbXvqvVfIosSGWym73S7+UxadvzDsLFwx6sgAOxMWhoyY2Lkcmt9YkI6oNAYmf5AZUgUhl/oSuXg4PJYOk1MimRv5etgqpTvwMQwQHRsZt4FPOlSLq6bL3R721PUQ3049/UBrom92I0FYGQJ6kjP1I7fRrC1yj2RPiqtVTOv3dsldvtaDj0j9dxkMhBiW3kwzN4cAMld60Q3llLEuaNcwmMANNeKjaeyEpXUUgtDgEIrL9+kSC/Qpkll3rh27uF3lUG4eLB5Ij0a6ABG+zHSau3gGM8/vrFWKOigdAlq2zMaa/Zp3hIp2rBEAKRt+YIR4hC9BnlxrP8d9Wm7vJB/EGWWiHb2kkiULpI5DFToX1w/8 jSvr3XuGtg9JopuRbK4Z6HJYRaJ9D+45 yHyYurSucqzakgDJER1WpfM3UZNcBvD2xgkbUb0vUdiVCvqz1E+/0I+OEzVb3p/w6ARI3SHENQGLTvdCkpW9HmAIWDwz8ONl6v2/8 yqAZFVpwJYmfqrYjUyWXmZZwsoNBgE5fg+SE2nkb90I7frKqRNiRfu7+V0NuL5T/dHHCaEXxuVxR3dm7h9hDmh/9 fnTWBTSIld4sKBmQY8wJNDziy0guKNOVO1TpSAcCWXUcpc913s1ycVWPY6eGfohZUrMu0C3WmuxGQEVHD3EPaU17fBCmxaGLm5SqaNY/g+P0kGNw0SZFybo/K6rk3c24M2zrSR6YiN2TGc+9 YpDDnV0PUH0vfcgThw8EPpmx0pJ4AgfqsbxYXOwo3OpMkiVZWjkfUj2yZiRypd+RybH7iJpd141kp8Y+H4r/o47GJ8D72D74f3AI25lJz0jtdnRE/UHJR9VAIRL9gTYVIxupObrJUcXbVEZ1sCEVx9NyZssoUiaTwDNazaLqHnmelCaqoetNEdWIt8" const res4 = decryptOutLink(text4); console.log("getOutLinkInfoV6 响应体解密结果:", res4); console.log("getOutLinkInfoV6 响应体加密结果:", encryptOutLink(res4)); 参考内容 139cloudsecret
前端
# 移动云盘
# CryptoJS
KongHen02
1年前
0
677
0
2025-10-12
蓝奏云 python sdk库
蓝奏云 Python 库使用文档 1. 配置与初始化 首先,准备 config.yaml 配置文件,内容示例: lanzou: username: "你的用户名" password: "你的密码"在代码中读取配置并初始化蓝奏云会话: import yaml from Lanzou import LanzouSession # 读取配置文件 with open("config.yaml", "r", encoding="utf-8") as f: config = yaml.safe_load(f) lanzou_conf = config["lanzou"] # 创建蓝奏云基础实例 session = LanzouSession() # 登录获取cookie status, result = session.login(lanzou_conf["username"], lanzou_conf["password"])2. 文件管理 2.1 创建文件管理实例 from Lanzou import LanzouFileManager file_manager = LanzouFileManager(session)2.2 重命名文件 status, result = file_manager.rename_file("文件ID", "新文件名.png") # 返回示例: # True { # "zt": 1, # "info": "重命名成功", # "text": None, # "dat": None # } # False { # "zt": 0, # "info": "会员已过期,无法使用", # "text": None, # "dat": None # }2.3 删除文件 status, result = file_manager.delete_file("文件ID") # 返回示例: # True { # "zt": 1, # "info": "已删除", # "text": None, # "dat": None # }2.4 上传文件 status, result = file_manager.upload_file("本地文件路径", "上传文件名.txt", "目标文件夹ID") # 返回示例: # True { # "zt": 1, # "info": "上传成功", # "text": [ # { # "icon": "txt", # "id": "246766304", # "f_id": "iYYAN31w12je", # "name_all": "上传测试.txt", # "name": "上传测试.txt", # "size": "18.0 B", # "time": "0 秒前", # "downs": "0", # "onof": "0", # "is_newd": "https://wwa.lanzouq.com" # } # ] # }2.5 移动文件 status, result = file_manager.move_file("文件ID", "目标文件夹ID") # 返回示例: # True { # "zt": 1, # "info": "移动成功", # "text": None, # "dat": None # }2.6 设置文件密码 status, result = file_manager.set_file_pwd("文件ID", "密码", "1") # 返回示例: # True { # "zt": 1, # "info": "设置成功", # "text": None, # "dat": None # }3. 文件夹管理 3.1 创建文件夹管理实例 from Lanzou import LanzouFolderManager folder_manager = LanzouFolderManager(session)3.2 创建文件夹 status, result = folder_manager.create_folder("文件夹名称", "父文件夹ID", "文件夹描述") # 返回示例: # True { # "zt": 1, # "info": "创建成功", # "text": "12296591", # "dat": None # }3.3 删除文件夹 status, result = folder_manager.delete_folder("文件夹ID") # 返回示例: # True { # "zt": 1, # "info": "删除成功", # "text": None, # "dat": None # }3.4 获取文件夹信息 status, result = folder_manager.get_folder_info("文件夹ID") # 返回示例: # True { # "zt": 1, # "info": { # "name": "测试2", # "des": "测试文件夹2", # "pwd": "1vo0", # "onof": "1", # "taoc": "", # "is_newd": "https://wwa.lanzouq.com", # "new_url": "https://wwa.lanzouq.com/b0rafeg1e" # }, # "text": None, # "dat": None # }3.5 修改文件夹信息 status, result = folder_manager.set_folder_info("文件夹ID", "新名称", "新描述") # 返回示例: # True { # "zt": 1, # "info": "成功修改", # "text": None, # "dat": None # }3.6 修改文件夹密码 status, result = folder_manager.set_folder_pwd("文件夹ID", "密码", "1") # 返回示例: # True { # "zt": 1, # "info": "修改成功", # "text": None, # "dat": None # }3.7 获取文件夹列表 status, result = folder_manager.get_folder_list("父文件夹ID") # 返回示例: # True { # "zt": 1, # "info": [ # { # "name": "测试", # "folder_des": "[测试文件夹]", # "folderid": 12295088, # "now": 1 # } # ], # "text": [ # { # "onof": "1", # "folderlock": "0", # "is_lock": "0", # "is_copyright": "0", # "name": "修改测试2", # "fol_id": "12295254", # "folder_des": "[修改测试文件夹2...]" # } # ], # "dat": null # }3.8 获取文件列表 status, result = folder_manager.get_file_list("文件夹ID") # 返回示例: # True { # "zt": 1, # "info": 1, # "text": [ # { # "icon": "jpg", # "id": "246767298", # "name_all": "EB9DA95273BC463B238A14588B7E6E8C.jpg", # "name": "EB9DA95273BC463B238A14588B7E6E8C.jpg", # "size": "342.3 K", # "time": "24 分钟前", # "downs": "0", # "onof": "0", # "is_lock": "0", # "filelock": "0", # "is_copyright": 0, # "is_bakdownload": 0, # "bakdownload": "0", # "is_des": 0, # "is_ico": 0 # } # ], # "dat": null # }4. 分享链接管理 4.1 创建分享管理实例 from Lanzou import LanzouShareManager share_manager = LanzouShareManager(session)4.2 获取文件分享链接 status, result = share_manager.get_file_link("文件ID") # 返回示例: # True { # "zt": 1, # "info": { # "pwd": "bofq", # "onof": "1", # "f_id": "it02C31w1u5i", # "taoc": "", # "is_newd": "https://wnwgongzuoshi.lanzouq.com" # }, # "text": None, # "dat": None # }4.3 获取文件夹分享链接 status, result = share_manager.get_folder_link("文件夹ID") # 返回示例: # True { # "zt": 1, # "info": { # "pwd": "bofq", # "onof": "1", # "f_id": "it02C31w1u5i", # "taoc": "", # "is_newd": "https://wnwgongzuoshi.lanzouq.com" # }, # "text": None, # "dat": None # }5. 他人分享链接下载 5.1 创建下载管理实例 from Lanzou import LanzouDownManager lanzouDown = LanzouDownManager()5.2 获取文件夹参数 status = lanzouDown.get_folder_params("分享链接URL")5.3 获取文件及文件夹列表 status, result = lanzouDown.get_file_list(url="分享链接URL", page=1)5.4 获取文件信息(包含下载链接) status, result = lanzouDown.get_file_info("文件分享链接", pwd="密码", final=True) # 返回示例: # True { # "title": "文件名称.apk", # "size": "57.0 M", # "author": "KongHen02", # "desc": "测试描述", # "url": "https://developer-oss.lanrar.com/file/...", # "down": "" # }5.5 通过下载链接获取下载直链 status, result = lanzouDown.get_final_url("下载链接")6. 打印输出 所有接口返回均为 (status, result),可直接打印: import json print(status, json.dumps(result, indent=4))7. 其他说明 各接口返回状态 status 为布尔值,True 表示成功,False 表示失败 返回结果中的 zt 字段:1 表示成功,0 表示失败 info 字段包含操作结果的详细信息 text 字段通常包含文件或文件夹的详细信息 分享链接管理需要用户登录后才能使用 他人分享链接下载不需要登录即可使用 如需更详细的参数说明或扩展用法,请参考源码或补充提问。 代码下载 cloud_driver_sdk 参考文献 openList
功能库
# python
# 蓝奏云
KongHen02
1年前
0
47
0
易航博客