Files
MeowOS-For-R3P2/patch_v2/ncm_app/REPORT.md
T

125 lines
9.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# os.meow.ncm 技术栈预研 + 构建验证报告
> 日期:2026-08-31。工作区:`/home/Aska/Project/R3ProII`,仅改动 `patch_v2/ncm_app/`。
> 目标:为 MeowOS 网易云 App(v1 = 扫码登录 + 我的歌单 + 播放)在 HiBy R3 Pro II
> (MIPS32r2 单核、~14MB 可用内存、无 GPU、ALSA 直开 hw:0,0)上的纯 C 静态栈做选型与真机交叉编译验证。
> 工具链:`.tools/zig-mipsel-cc`(zig 包装 mipsel-linux-musleabi soft-float 静态交叉)。全程未 commit/push/刷机/动设备。
## 1. 选型结论表
| 能力 | 选型 | 版本 | 许可 | mipsel 体积(text) | 说明 |
|---|---|---|---|---|---|
| TLS + 加密 | **mbedtls(裁剪)** | 3.6.2 | Apache-2.0 | 链接 Demo ≈ **388 KB** | TLS1.2 client + AES-128-CBC/ECB/GCM + MD5 + RSA(1024 raw) + Base64 + X509,单库全包 |
| TLS(备选) | BearSSL | master@7bea48e | MIT | TLS client 子集 ≈ **96 KB** | 更省 flash,但无 base64、AES-ECB 需自行逐块、RSA raw 用 `br_rsa_i31_public` |
| JSON | **jsmn** | 1.1.0 | MIT | **2.2 KB** | 分词器,无 malloc/无 DOM;cJSON 对比 20 KB |
| 二维码 | **qrcodegen** | nayuki@993ccbb | MIT | **10.8 KB** | 纯 C 单文件,无图形依赖 |
| MP3 解码 | **minimp3** | master@ea99364 | CC0 | **37.4 KB** | `minimp3_ex` 流式/可 seek;dr_mp3 对比 40.7 KB |
**HTTPS GET/POST 可达性**:mbedtls 已实测连通(见 §2)。**crypto 是否 mbedtls 自带就够**:是——
AES-128-ECB/CBC、MD5、Base64、RSA(raw) 全有;RSA raw 用 `mbedtls_rsa_public()`(无 padding 纯模幂)已交叉校验与 `pow(m,e,n)` 完全一致(见 §3),这是文档标注最易踩坑处,已验证可行。
## 2. HTTPS 实测(宿主 = 本机 aarch64;另跑通 MIPS 版)
**demo**:`demo/https_unikey.c`(mbedtls TLS1.2 + eapi 加密 + jsmn)。
目标:`POST https://interface.music.163.com/eapi/login/qrcode/unikey`,body `params=<eapi hex>`。
```
deviceId=68DFA27096B7A5DC2CB393C77D8C194FDC0459B743081D091EBD
---- response body ----
{"code":200,"unikey":"33a1c6a6-28ad-4e1e-bc8e-ebe769953913"}
UNIKEY = 33a1c6a6-28ad-4e1e-bc8e-ebe769953913
```
- 宿主:`code:200` + unikey 顶层字段,与 NCM_API_NOTES §7 一致 ✅
- **MIPS 版交叉编译后,在 `qemu-mipsel` 下全链路跑通**(DNS→TCP→TLS→POST→JSON 解析),同样拿到真实 unikey:
`{"code":200,"unikey":"6731b1ac-71a2-41eb-a704-a2de39d6d0b7"}`。即 mipsel 静态产物的网络+crypto+TLS 路径正确。
- eapi 加密逻辑与原版 `crypto::eapi` 一致:`digest=md5("nobody"+url+"use"+json+"md5forencrypt")`,
`plain=url+"-36cd479b6b5-"+json+"-36cd479b6b5-"+digest`,`params=HEX_UPPER(AES128ECB(plain,"e82ckenh8dichen8"))`;
`header`(osver/deviceId/os/appver/versioncode/mobilename/buildver/resolution/__csrf/channel/requestId)与 `e_r:false` 均入加密体(§8 要求,去掉会 4xx)。
## 3. RSA raw(weapi 无 padding 模幂)校验
`mbedtls_rsa_public(ctx, 128B输入右对齐16B明文, 128B输出)`,n=1024-bit、e=65537。
- mipsel(qemu) 与宿主输出一致,且与 Python `pow(m,e,n)` 逐一字节相同(256 hex 完全匹配):
`CT = 55B33E7E3229B8D977137D120B3C7A5B5FB8E933325CAA5BB8CEF6C132D57E5E...B2B83`
- 结论:**mbedtls_rsa_public() 可用作 weapi 的 textbook RSA**,避开 PKCS#1 padding 陷阱。demo:`demo/rsa_raw_test.c`。
## 4. 总体积账(mipsel,-Os,flash≈text)
**选定的库合计(≈438 KB)**:
| 项 | text | 备注 |
|---|---|---|
| mbedtls TLS+crypto+x509(链接 demo) | 388 KB | 含 ~6 KB musl libc 基线;库文本合计 410 KB,gc-sections 未再降 |
| jsmn | 2.2 KB | |
| qrcodegen | 10.8 KB | |
| minimp3 | 37.4 KB | |
| **库合计** | **≈ 438 KB** | 另需 App/UI/封面/音频输出层(未计入,自研) |
可选裁剪方向(能明显压 mbedtls):限制密码套件到 `TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256`(+1 个 CBC+SHA 兜底)、
ECP 只留 P-256、去掉 ECDSA(服务器给 RSA 证书)、`MBEDTLS_SSL_IN/OUT_CONTENT_LEN=4096`。估可降到 ~250 KB。
若固件预算仍紧,**切 BearSSL(≈96KB) + 自带 base64/AES-ECB 例程**,能再省 ~300 KB。
**对比参考项体积**:cJSON 20 KB、dr_mp3 40.7 KB、BearSSL 全库 310 KB(裁剪子集 96 KB)。空静态 mipsel 基线 text=5888。
## 5. 内存 / 性能估算(14MB 可用)
- **TLS 握手 buffer**:mbedtls 默认 `SSL_IN/OUT_CONTENT_LEN`=16KB 各一,共 ~32KB;demo 二进制 `bss=26888`(≈26KB)+堆内 SSL context/ECDH 临时密钥。对 14MB 无压力;建议调成 4096 更省。
- **JSON 解析**:jsmn 无 malloc,token 数组按需分配(响应小,几百字节)。**不要全量缓冲歌单详情**,只取需要的键(文档 §4.4)。
- **解码**:minimp3 流式,输入 ~每帧几 KB + 输出 `MINIMP3_MAX_SAMPLES_PER_FRAME*2*ch`,整体 <20KB。
- **封面**:**必须限幅**——NCM 建议 5MB,MeowOS 应限 ~256KB 并降采样/调色板(无 GPU 只能 CPU 软缩放)。
- **二维码位图**:41×41 符号渲染成 UI 尺寸(如 400×400,灰度 1B/px=160KB,1-bit 可 20KB)。
- 预算结论:TLS+解码+二维码+封面(256KB cap)+UI 帧缓冲,**总工作集应在数百 KB 量级,14MB 富余**;唯一要盯的是封面/歌单响应别全量驻留。
- **性能**:
- **MP3 解码实时性**:宿主(aarch64) minimp3 = **568×RT**、dr_mp3 = 627×RT;
`qemu-mipsel`(TCG 模拟,**远慢于真机**,通常 10–50×) 下 minimp3 = **4.8×RT**、dr_mp3 = 4.7×RT。
→ 真机 MIPS32 单核跑 44.1k/64kbps 解码**余量很大**(估计数十倍 RT),解码不是瓶颈。⚠️ 该数字为宿主/模拟估算,标注不准。
- **TLS 握手**:ECDHE-RSA-AES128-GCM,单核软 RSA 1024 校验 + ECDH P-256,估几十~几百 ms,可接受(仅首次/重连)。
- **weapi RSA raw 模幂**:1024-bit 软模幂每次约几 ms~几十 ms(只对 weapi 请求,频率低)。
## 6. 风险与 fallback
| 风险 | 评估 | 对策/fallback |
|---|---|---|
| weapi RSA raw 最易踩坑 | ✅ 已交叉校验正确 | 保持 `mbedtls_rsa_public()`+左补零到 256 hex;用 `rsa_raw_test` 做回归 |
| deviceId/UA 不稳定触发风控 | 高 | deviceId(52 hex) **首生成后持久化**;UA 按 eapi(iPhone)/weapi(Chrome) 分别固定;轮询≥1s、失败退避 |
| session(MUSIC_U)丢失即需重扫码 | 高 | cookie 持久化;启动用 `/weapi/w/nuser/account/get` 校验 |
| eapi 的 `header`/`e_r` 缺失 → 4xx | 中 | demo 已带,必须保留(§8) |
| 无版权/VIP 曲目 url=null | 中 | `song_url_v1` 返回 null → 提示 + 降级到 `song/enhance/player/url`(br=320000) 兜底 |
| 音质策略(Hi-res 降级) | v1 只保 mp3 | 账号非免费档 level 被钳到免费档;v1 默认 `standard`(128k)/`higher`(192k);**不引入 flac 解码**(14MB 内存+单核不划算);后续再评估 dr_flac |
| 触发高频风控 | 中 | 请求限频、重试退避、必要时随机国内 IP(`X-Real-IP`/`X-Forwarded-For`) |
| mbedtls flash ~388KB 偏大 | 中 | 见 §4 裁剪;若预算吃紧切 BearSSL(≈96KB) |
## 7. 出入清单(只改 `patch_v2/ncm_app/`)
```
patch_v2/ncm_app/
├── vendor/ # 各库源码(上游 clone/tar + 许可证)
│ ├── mbedtls/ (3.6.2, 含 framework 子模块, 裁剪 config 在 config/mbedtls_config_ncm.h)
│ ├── bearssl/ (官方 git, 无语义版本)
│ ├── jsmn/ cjson/ qrcodegen/ minimp3/ dr_mp3/
├── libs_common.sh # 公共 zig/ar/size 环境
├── build_mbedtls.sh # 裁剪 config + 静态编 mipsel → out/mbedtls/mipsel/*.a
├── build_bearssl.sh # make lib → out/bearssl/mipsel/bm/libbearssl.a
├── build_cjson.sh build_jsmn.sh build_qrcodegen.sh build_minimp3.sh build_dr_mp3.sh
├── build_demo.sh # 宿主 + mipsel 的 HTTPS demo 复现
├── bench/ # minimp3/dr_mp3 基准(sample-15s.mp3 来自 samplelib)
├── demo/https_unikey.c # eapi + TLS1.2 + jsmn(打 unikey)
├── demo/rsa_raw_test.c # weapi RSA raw 校验
├── out/https_unikey_mipsel(. _s) # mipsel 静态 demo(qemu-mipsel 跑通)
├── out/mbedtls/{mipsel,host}/ # 库产物 out/bearssl/mipsel/bm/
├── VENDOR_NOTES.md # 版本/许可/裁剪/体积
└── REPORT.md # 本报告
```
**未做/待主会话**:真机 `hw:0,0` 播放链路、扫码后真实登录(803+set-cookie)、weapi 真实登录态请求、
CA bundle 内置方案、音质档位映射实测。这些属设备/账号侧联调,由主会话在设备上执行(本预研不动设备)。
## 8. 结论
- **可行**:纯 C + mbedtls(裁剪) + jsmn + qrcodegen + minimp3,静态 mipsel 交叉编译全通,HTTPS POST 拿到真实 unikey,MIPS(qemu) 版全链路跑通。
- **推荐 TLS/加密一体用 mbedtls**(单库一次解决 TLS + AES/MD5/RSA raw/Base64 + X509,规避 RNSS-raw 手写风险);BearSSL 为省 flash 备选。
- **v1 体积增量 ≈ 438 KB(库)/ 只做 mp3**,内存估计数百 KB 工作集,14MB 可行;主要优化点是 mbedtls 裁剪与封面限幅。
- **最关键风险(RSA raw)已验证**;其余风险集中在风控(deviceId/UA 稳定持久化)与无版权降级策略。