mirror of
https://github.com/truewhile/MeBox.git
synced 2026-09-28 03:06:38 +08:00
b0fe40142a
* Rebrand MMTL to MeBox across codebase and assets Rename the project display name, Go module path, environment variable prefix (MEBOX_*), Docker image references, and UI branding from MMTL/mmtl to MeBox/mebox. Replace logo assets with the new MeBox icon and keep legacy SQLite migration support for existing mmtl.db deployments. Co-authored-by: truewhile <truewhile@users.noreply.github.com> * Fix logo icons: use cube-only crop without truncated text Previous icon generation cropped too much of the source image, including partial MeBox wordmark text that was cut off in square icon containers. Regenerate logo-64/192/512, favicon, and SVG from cube-only region. Co-authored-by: truewhile <truewhile@users.noreply.github.com> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: truewhile <truewhile@users.noreply.github.com>
66 lines
2.6 KiB
Go
66 lines
2.6 KiB
Go
// Package service — 内置 dandanplay 应用凭据(签名认证回退用)。
|
||
//
|
||
// 弹弹play 开放 API(https://doc.dandanplay.com/open/)要求所有请求
|
||
// 携带应用认证。官方推荐客户端应用使用「签名验证模式」:
|
||
//
|
||
// 请求头 X-AppId + X-Timestamp + X-Signature
|
||
// X-Signature = base64(sha256(AppId + Timestamp + Path + AppSecret))
|
||
//
|
||
// Timestamp 为 UTC 秒级 Unix 时间戳,Path 为不含域名/查询参数的请求路径。
|
||
// 该模式里 AppSecret 只存在于服务端本地,网络上传输的只有绑定
|
||
// 时间戳与路径的签名,无法重放到其它请求上——这是「隐藏密钥」真正
|
||
// 有效的部分。
|
||
//
|
||
// 为了让用户开箱即用,这里内置了一组项目自用凭据作为回退(在
|
||
// DevCenter 申请)。管理员可在「弹幕」设置页填写自己的 AppId /
|
||
// AppSecret 覆盖内置凭据。
|
||
//
|
||
// 混淆说明(重要):开源项目无法真正隐藏随二进制分发的密钥,XOR
|
||
// 混淆只能挡住直接扫源码/复制常量这种程度的提取,挡不住反编译内存
|
||
// 取证。因此内置凭据只作为回退,不建议过度依赖它承载大流量。
|
||
package service
|
||
|
||
import (
|
||
"crypto/sha256"
|
||
"encoding/base64"
|
||
"encoding/hex"
|
||
"strconv"
|
||
)
|
||
|
||
// dandanplayObfuscationKey 是解开内置凭据的 XOR 混淆密钥。它与密文
|
||
// 同处一个二进制,仅作提取门槛,不作安全边界。
|
||
const dandanplayObfuscationKey = "MeBox-Danmaku#2026!v2"
|
||
|
||
// 内置回退凭据(XOR 混淆后的 hex 编码)。
|
||
const (
|
||
danmakuEmbeddedAppIDHex = "350432560a153452095e"
|
||
danmakuEmbeddedAppKeyHex = "74111b564d5b1256141907594149677a5c717721550535331c0e4327071d0b2c"
|
||
)
|
||
|
||
// danmakuEmbeddedCredentials 解出内置回退凭据。
|
||
func danmakuEmbeddedCredentials() (appID, appKey string) {
|
||
return xorDecode(danmakuEmbeddedAppIDHex), xorDecode(danmakuEmbeddedAppKeyHex)
|
||
}
|
||
|
||
// xorDecode 用 dandanplayObfuscationKey 逐字节解开 hex 密文。
|
||
func xorDecode(hexStr string) string {
|
||
raw, err := hex.DecodeString(hexStr)
|
||
if err != nil {
|
||
return ""
|
||
}
|
||
key := []byte(dandanplayObfuscationKey)
|
||
out := make([]byte, len(raw))
|
||
for i, b := range raw {
|
||
out[i] = b ^ key[i%len(key)]
|
||
}
|
||
return string(out)
|
||
}
|
||
|
||
// dandanplaySignature 计算开放 API 请求签名:
|
||
// base64(sha256(AppId + Timestamp + Path + AppSecret))。
|
||
// path 只含请求路径(不含域名与查询参数、小写、不 URL 编码)。
|
||
func dandanplaySignature(appID, appSecret string, ts int64, path string) string {
|
||
sum := sha256.Sum256([]byte(appID + strconv.FormatInt(ts, 10) + path + appSecret))
|
||
return base64.StdEncoding.EncodeToString(sum[:])
|
||
}
|