mirror of
https://github.com/truewhile/MeBox.git
synced 2026-10-05 13:06:36 +08:00
feat(reader): P2——goja JS 引擎接入 + Go 原生 java.* 桥接
- rule/goja.go:纯 Go JS 运行时(goja),脚本编译缓存 + 超时中断(默认10s),
绑定集合对齐 legado evalJS(java/cookie/cache/source/book/result/baseUrl/
chapter/title/src/page/key)
- rule/bridge.go:java 对象函数名与 legado JsExtensions 一一对应(存量书源
硬编码这些名字),全部 Go 原生实现:
网络 ajax/ajaxAll/connect/get/post/head(经 MeBox HTTP 客户端,响应对象
带 body()/code()/url()/header());规则回调 getString/getStringList/
getElements/put/get(桥回当前解析器);编解码 base64/hex/md5(16/32)/
digest/HMac/encodeURI/timeFormat(SimpleDateFormat 转 Go 布局)
- 对称加密:createSymmetricCrypto + aes/des/3des 全家桶,transformation
三段式解析(AES/DES/3DES × CBC/ECB/CTR/OFB/CFB × PKCS5/7/Zero/NoPadding,
ECB 手工块循环),密钥长度自动补齐,decryptStr 自动识别 Base64/Hex
- get(url,headers) 与 get(key) 按 arity 分发(对齐 Kotlin 重载)
- 浏览器/文件/压缩包类函数明确抛不支持(服务端沙箱边界)
- URL 规则 JS:analyzeJs(@result 链式)、{{js}} 内嵌、option js/bodyJs
- execute 记录 Set-Cookie 进 cookie jar(java/cookie.getCookie 可读)
- 测试:编码/摘要/AES 向量/CBC+ECB 往返/ajax httptest/URL JS/沙箱边界,
全部通过;修复 java.get 双注册、测试缺 SetContent 与 md5Encode16 期望值
This commit is contained in:
@@ -0,0 +1,467 @@
|
||||
package rule
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/md5"
|
||||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"hash"
|
||||
"strings"
|
||||
|
||||
"github.com/dop251/goja"
|
||||
)
|
||||
|
||||
// 本文件对应 legado JsExtensions / JsEncodeUtils / RegexJsExtensions 中
|
||||
// 注入为 `java` 对象的函数。函数名与 Kotlin 版一一对应(存量书源硬编码),
|
||||
// 实现全部为 Go 原生;浏览器/文件/压缩包类能力明确抛出不支持错误。
|
||||
|
||||
func newJavaObject(vm *goja.Runtime, r *JSRunner, a *AnalyzeRule) *goja.Object {
|
||||
o := vm.NewObject()
|
||||
set := func(k string, v any) {
|
||||
if err := o.Set(k, v); err != nil {
|
||||
panic(vm.ToValue(err.Error()))
|
||||
}
|
||||
}
|
||||
|
||||
bridgeErr := func(name string, err error) goja.Value {
|
||||
panic(vm.ToValue(fmt.Sprintf("java.%s: %v", name, err)))
|
||||
}
|
||||
|
||||
// ── 网络(对应 JsExtensions.ajax/ajaxAll/connect/get/post/head) ──
|
||||
fetchStr := func(name string, urlVal goja.Value, extraHeaders map[string]any) string {
|
||||
if r.cfg.Fetch == nil {
|
||||
bridgeErr(name, ErrJsUnsupported)
|
||||
}
|
||||
urlStr := urlVal.String()
|
||||
if arr, ok := urlVal.Export().([]any); ok && len(arr) > 0 {
|
||||
urlStr = fmt.Sprintf("%v", arr[0]) // 对应 legado:List 取第一个
|
||||
}
|
||||
req, err := ParseAnalyzeUrlWithJS(urlStr, "", 0, r.cfg.BaseURL, r)
|
||||
if err != nil {
|
||||
bridgeErr(name, err)
|
||||
}
|
||||
if req.Unsupported != nil {
|
||||
bridgeErr(name, req.Unsupported)
|
||||
}
|
||||
for k, v := range extraHeaders {
|
||||
if _, exists := req.Headers[k]; !exists {
|
||||
req.Headers[k] = fmt.Sprintf("%v", v)
|
||||
}
|
||||
}
|
||||
body, _, _, err := r.cfg.Fetch(req)
|
||||
if err != nil {
|
||||
bridgeErr(name, err)
|
||||
}
|
||||
return body
|
||||
}
|
||||
|
||||
fetchResp := func(name string, args []goja.Value, method, body string) *goja.Object {
|
||||
if r.cfg.Fetch == nil {
|
||||
bridgeErr(name, ErrJsUnsupported)
|
||||
}
|
||||
urlStr := ""
|
||||
if len(args) > 0 {
|
||||
urlStr = args[0].String()
|
||||
}
|
||||
req, err := ParseAnalyzeUrlWithJS(urlStr, "", 0, r.cfg.BaseURL, r)
|
||||
if err != nil {
|
||||
bridgeErr(name, err)
|
||||
}
|
||||
if method == "POST" {
|
||||
req.Method = "POST"
|
||||
req.Body = body
|
||||
trimmed := strings.TrimSpace(body)
|
||||
if strings.HasPrefix(trimmed, "{") || strings.HasPrefix(trimmed, "[") {
|
||||
req.IsJSON = true
|
||||
} else if body != "" {
|
||||
req.IsForm = true
|
||||
req.Body = encodeParams(body, req.Charset, false)
|
||||
}
|
||||
}
|
||||
if len(args) > 1 && !goja.IsUndefined(args[1]) && !goja.IsNull(args[1]) {
|
||||
if extra, ok := args[1].Export().(map[string]any); ok {
|
||||
for k, v := range extra {
|
||||
req.Headers[k] = fmt.Sprintf("%v", v)
|
||||
}
|
||||
}
|
||||
}
|
||||
if req.Unsupported != nil {
|
||||
bridgeErr(name, req.Unsupported)
|
||||
}
|
||||
respBody, finalURL, code, err := r.cfg.Fetch(req)
|
||||
if err != nil {
|
||||
bridgeErr(name, err)
|
||||
}
|
||||
return newResponseObject(vm, respBody, code, finalURL, nil)
|
||||
}
|
||||
|
||||
set("ajax", func(call goja.FunctionCall) goja.Value {
|
||||
extra := map[string]any(nil)
|
||||
if len(call.Arguments) > 1 && !goja.IsUndefined(call.Arguments[1]) && !goja.IsNull(call.Arguments[1]) {
|
||||
if m, ok := call.Arguments[1].Export().(map[string]any); ok {
|
||||
extra = m
|
||||
}
|
||||
}
|
||||
return vm.ToValue(fetchStr("ajax", call.Arguments[0], extra))
|
||||
})
|
||||
set("ajaxAll", func(call goja.FunctionCall) goja.Value {
|
||||
var urls []any
|
||||
if len(call.Arguments) > 0 {
|
||||
if arr, ok := call.Arguments[0].Export().([]any); ok {
|
||||
urls = arr
|
||||
}
|
||||
}
|
||||
out := make([]any, 0, len(urls))
|
||||
for _, u := range urls {
|
||||
out = append(out, fetchStr("ajaxAll", vm.ToValue(u), nil))
|
||||
}
|
||||
return vm.ToValue(out)
|
||||
})
|
||||
set("connect", func(call goja.FunctionCall) goja.Value {
|
||||
return fetchResp("connect", call.Arguments, "GET", "")
|
||||
})
|
||||
// get 双语义(对应 Kotlin 重载):get(url, headers) 走网络,get(key) 读变量
|
||||
set("get", func(call goja.FunctionCall) goja.Value {
|
||||
if len(call.Arguments) >= 2 && !goja.IsUndefined(call.Arguments[1]) && !goja.IsNull(call.Arguments[1]) {
|
||||
return fetchResp("get", call.Arguments, "GET", "")
|
||||
}
|
||||
key := stringArg(call, 0)
|
||||
if a != nil {
|
||||
return vm.ToValue(a.Get(key))
|
||||
}
|
||||
return vm.ToValue(r.vars[key])
|
||||
})
|
||||
set("post", func(call goja.FunctionCall) goja.Value {
|
||||
body := stringArgOr(call, 1, "")
|
||||
return fetchResp("post", call.Arguments, "POST", body)
|
||||
})
|
||||
set("head", func(call goja.FunctionCall) goja.Value {
|
||||
return fetchResp("head", call.Arguments, "HEAD", "")
|
||||
})
|
||||
|
||||
// ── 规则回调(桥回当前 AnalyzeRule,对应 AnalyzeRule.getString 等公有方法) ──
|
||||
ruleStr := func(name string, args []goja.Value) (string, error) {
|
||||
if a == nil {
|
||||
return "", fmt.Errorf("无规则上下文")
|
||||
}
|
||||
mContent := any(nil)
|
||||
if len(args) > 1 && !goja.IsUndefined(args[1]) && !goja.IsNull(args[1]) {
|
||||
mContent = args[1].Export()
|
||||
}
|
||||
isURL := len(args) > 2 && args[2].ToBoolean()
|
||||
return a.GetString(args[0].String(), mContent, isURL)
|
||||
}
|
||||
set("getString", func(call goja.FunctionCall) goja.Value {
|
||||
s, err := ruleStr("getString", call.Arguments)
|
||||
if err != nil {
|
||||
bridgeErr("getString", err)
|
||||
}
|
||||
return vm.ToValue(s)
|
||||
})
|
||||
set("getStringList", func(call goja.FunctionCall) goja.Value {
|
||||
if a == nil {
|
||||
return goja.Null()
|
||||
}
|
||||
list, err := a.GetStringList(stringArgOr(call, 0, ""), nil, false)
|
||||
if err != nil {
|
||||
bridgeErr("getStringList", err)
|
||||
}
|
||||
return vm.ToValue(list)
|
||||
})
|
||||
set("getElements", func(call goja.FunctionCall) goja.Value {
|
||||
if a == nil {
|
||||
return goja.Null()
|
||||
}
|
||||
els, err := a.GetElements(stringArgOr(call, 0, ""))
|
||||
if err != nil {
|
||||
bridgeErr("getElements", err)
|
||||
}
|
||||
out := make([]any, 0, len(els))
|
||||
for _, el := range els {
|
||||
out = append(out, resultString(el))
|
||||
}
|
||||
return vm.ToValue(out)
|
||||
})
|
||||
set("put", func(call goja.FunctionCall) goja.Value {
|
||||
key := stringArg(call, 0)
|
||||
val := stringArgOr(call, 1, "")
|
||||
if a != nil {
|
||||
return vm.ToValue(a.Put(key, val))
|
||||
}
|
||||
r.vars[key] = val
|
||||
return vm.ToValue(val)
|
||||
})
|
||||
|
||||
// ── 编码(对应 JsEncodeUtils / JsExtensions) ──
|
||||
set("md5Encode", func(call goja.FunctionCall) goja.Value {
|
||||
return vm.ToValue(md5Hex(stringArg(call, 0), false))
|
||||
})
|
||||
set("md5Encode16", func(call goja.FunctionCall) goja.Value {
|
||||
return vm.ToValue(md5Hex(stringArg(call, 0), true))
|
||||
})
|
||||
set("base64Decode", func(call goja.FunctionCall) goja.Value {
|
||||
s, err := base64DecodeString(stringArg(call, 0))
|
||||
if err != nil {
|
||||
bridgeErr("base64Decode", err)
|
||||
}
|
||||
return vm.ToValue(s)
|
||||
})
|
||||
set("base64DecodeToByteArray", func(call goja.FunctionCall) goja.Value {
|
||||
b, err := base64DecodeBytes(stringArg(call, 0))
|
||||
if err != nil {
|
||||
bridgeErr("base64DecodeToByteArray", err)
|
||||
}
|
||||
return vm.ToValue(vm.NewArrayBuffer(b))
|
||||
})
|
||||
set("base64Encode", func(call goja.FunctionCall) goja.Value {
|
||||
return vm.ToValue(base64.StdEncoding.EncodeToString([]byte(stringArg(call, 0))))
|
||||
})
|
||||
set("hexDecodeToString", func(call goja.FunctionCall) goja.Value {
|
||||
b, err := hex.DecodeString(strings.TrimSpace(stringArg(call, 0)))
|
||||
if err != nil {
|
||||
bridgeErr("hexDecodeToString", err)
|
||||
}
|
||||
return vm.ToValue(string(b))
|
||||
})
|
||||
set("hexDecodeToByteArray", func(call goja.FunctionCall) goja.Value {
|
||||
b, err := hex.DecodeString(strings.TrimSpace(stringArg(call, 0)))
|
||||
if err != nil {
|
||||
bridgeErr("hexDecodeToByteArray", err)
|
||||
}
|
||||
return vm.ToValue(vm.NewArrayBuffer(b))
|
||||
})
|
||||
set("hexEncodeToString", func(call goja.FunctionCall) goja.Value {
|
||||
return vm.ToValue(hex.EncodeToString([]byte(stringArg(call, 0))))
|
||||
})
|
||||
set("strToBytes", func(call goja.FunctionCall) goja.Value {
|
||||
return vm.ToValue(vm.NewArrayBuffer([]byte(stringArg(call, 0))))
|
||||
})
|
||||
set("bytesToStr", func(call goja.FunctionCall) goja.Value {
|
||||
if len(call.Arguments) == 0 || goja.IsUndefined(call.Arguments[0]) || goja.IsNull(call.Arguments[0]) {
|
||||
return vm.ToValue("")
|
||||
}
|
||||
if buf, ok := call.Arguments[0].Export().([]byte); ok {
|
||||
return vm.ToValue(string(buf))
|
||||
}
|
||||
return vm.ToValue(call.Arguments[0].String())
|
||||
})
|
||||
set("encodeURI", func(call goja.FunctionCall) goja.Value {
|
||||
return vm.ToValue(javaURLEncode(stringArg(call, 0), stringArgOr(call, 1, "utf-8")))
|
||||
})
|
||||
set("timeFormat", func(call goja.FunctionCall) goja.Value {
|
||||
ts := int64(call.Arguments[0].ToFloat())
|
||||
format := stringArgOr(call, 1, "yyyy-MM-dd HH:mm")
|
||||
return vm.ToValue(javaTimeFormat(ts, format, 0))
|
||||
})
|
||||
set("timeFormatUTC", func(call goja.FunctionCall) goja.Value {
|
||||
ts := int64(call.Arguments[0].ToFloat())
|
||||
format := stringArgOr(call, 1, "yyyy-MM-dd HH:mm")
|
||||
sh := int64(0)
|
||||
if len(call.Arguments) > 2 {
|
||||
sh = int64(call.Arguments[2].ToFloat())
|
||||
}
|
||||
return vm.ToValue(javaTimeFormat(ts, format, sh))
|
||||
})
|
||||
|
||||
// ── 加解密(对应 JsEncodeUtils) ──
|
||||
set("createSymmetricCrypto", func(call goja.FunctionCall) goja.Value {
|
||||
transformation := stringArgOr(call, 0, "AES/CBC/PKCS5Padding")
|
||||
key := stringArgOr(call, 1, "")
|
||||
iv := stringArgOr(call, 2, "")
|
||||
cipher, err := newSymmetricCipher(transformation, key, iv)
|
||||
if err != nil {
|
||||
bridgeErr("createSymmetricCrypto", err)
|
||||
}
|
||||
return newCipherObject(vm, cipher)
|
||||
})
|
||||
aesVariant := func(mode string) func(goja.FunctionCall) goja.Value {
|
||||
return func(call goja.FunctionCall) goja.Value {
|
||||
data := stringArg(call, 0)
|
||||
key := stringArgOr(call, 1, "")
|
||||
defaultTrans := mode
|
||||
trans := stringArgOr(call, 2, defaultTrans)
|
||||
iv := stringArgOr(call, 3, "")
|
||||
cipher, err := newSymmetricCipher(trans, key, iv)
|
||||
if err != nil {
|
||||
bridgeErr(mode, err)
|
||||
}
|
||||
out, err := cipher.decryptAuto(data)
|
||||
if err != nil {
|
||||
bridgeErr(mode, err)
|
||||
}
|
||||
return vm.ToValue(string(out))
|
||||
}
|
||||
}
|
||||
set("aesDecodeToString", aesVariant("AES/CBC/PKCS5Padding"))
|
||||
set("aesBase64DecodeToString", aesVariant("AES/CBC/PKCS5Padding"))
|
||||
set("aesBase64DecodeToByteArray", aesVariant("AES/CBC/PKCS5Padding"))
|
||||
set("desDecodeToString", aesVariant("DES/CBC/PKCS5Padding"))
|
||||
set("desBase64DecodeToString", aesVariant("DES/CBC/PKCS5Padding"))
|
||||
encryptStr := func(data, key, trans, iv string) string {
|
||||
cipher, err := newSymmetricCipher(trans, key, iv)
|
||||
if err != nil {
|
||||
bridgeErr("encrypt", err)
|
||||
}
|
||||
out, err := cipher.encrypt([]byte(data))
|
||||
if err != nil {
|
||||
bridgeErr("encrypt", err)
|
||||
}
|
||||
return string(out)
|
||||
}
|
||||
set("aesEncodeToString", func(call goja.FunctionCall) goja.Value {
|
||||
return vm.ToValue(encryptStr(stringArg(call, 0), stringArgOr(call, 1, ""), stringArgOr(call, 2, "AES/CBC/PKCS5Padding"), stringArgOr(call, 3, "")))
|
||||
})
|
||||
set("desEncodeToString", func(call goja.FunctionCall) goja.Value {
|
||||
return vm.ToValue(encryptStr(stringArg(call, 0), stringArgOr(call, 1, ""), stringArgOr(call, 2, "DES/CBC/PKCS5Padding"), stringArgOr(call, 3, "")))
|
||||
})
|
||||
encryptB64 := func(data, key, trans, iv string) string {
|
||||
cipher, err := newSymmetricCipher(trans, key, iv)
|
||||
if err != nil {
|
||||
bridgeErr("encrypt", err)
|
||||
}
|
||||
out, err := cipher.encrypt([]byte(data))
|
||||
if err != nil {
|
||||
bridgeErr("encrypt", err)
|
||||
}
|
||||
return base64.StdEncoding.EncodeToString(out)
|
||||
}
|
||||
set("aesEncodeToBase64String", func(call goja.FunctionCall) goja.Value {
|
||||
return vm.ToValue(encryptB64(stringArg(call, 0), stringArgOr(call, 1, ""), stringArgOr(call, 2, "AES/CBC/PKCS5Padding"), stringArgOr(call, 3, "")))
|
||||
})
|
||||
set("desEncodeToBase64String", func(call goja.FunctionCall) goja.Value {
|
||||
return vm.ToValue(encryptB64(stringArg(call, 0), stringArgOr(call, 1, ""), stringArgOr(call, 2, "DES/CBC/PKCS5Padding"), stringArgOr(call, 3, "")))
|
||||
})
|
||||
set("tripleDESDecodeStr", func(call goja.FunctionCall) goja.Value {
|
||||
data := stringArg(call, 0)
|
||||
key := stringArgOr(call, 1, "")
|
||||
trans := "DESede/CBC/PKCS5Padding"
|
||||
var ivv string
|
||||
switch {
|
||||
case len(call.Arguments) > 4: // (data, key, mode, padding, iv)
|
||||
trans = "DESede/" + stringArgOr(call, 2, "CBC") + "/" + stringArgOr(call, 3, "PKCS5Padding")
|
||||
ivv = stringArgOr(call, 4, "")
|
||||
case len(call.Arguments) > 2: // (data, key, transformation, iv?)
|
||||
trans = stringArgOr(call, 2, trans)
|
||||
ivv = stringArgOr(call, 3, "")
|
||||
}
|
||||
cipher, err := newSymmetricCipher(trans, key, ivv)
|
||||
if err != nil {
|
||||
bridgeErr("tripleDESDecodeStr", err)
|
||||
}
|
||||
out, err := cipher.decryptAuto(data)
|
||||
if err != nil {
|
||||
bridgeErr("tripleDESDecodeStr", err)
|
||||
}
|
||||
return vm.ToValue(string(out))
|
||||
})
|
||||
set("digestHex", func(call goja.FunctionCall) goja.Value {
|
||||
h, err := digestHash(stringArgOr(call, 1, "MD5"))
|
||||
if err != nil {
|
||||
bridgeErr("digestHex", err)
|
||||
}
|
||||
h.Write([]byte(stringArg(call, 0)))
|
||||
return vm.ToValue(hex.EncodeToString(h.Sum(nil)))
|
||||
})
|
||||
set("digestBase64Str", func(call goja.FunctionCall) goja.Value {
|
||||
h, err := digestHash(stringArgOr(call, 1, "MD5"))
|
||||
if err != nil {
|
||||
bridgeErr("digestBase64Str", err)
|
||||
}
|
||||
h.Write([]byte(stringArg(call, 0)))
|
||||
return vm.ToValue(base64.StdEncoding.EncodeToString(h.Sum(nil)))
|
||||
})
|
||||
set("HMacHex", func(call goja.FunctionCall) goja.Value {
|
||||
h, err := hmacHash(stringArgOr(call, 1, "HmacSHA256"), []byte(stringArgOr(call, 2, "")))
|
||||
if err != nil {
|
||||
bridgeErr("HMacHex", err)
|
||||
}
|
||||
h.Write([]byte(stringArg(call, 0)))
|
||||
return vm.ToValue(hex.EncodeToString(h.Sum(nil)))
|
||||
})
|
||||
set("HMacBase64", func(call goja.FunctionCall) goja.Value {
|
||||
h, err := hmacHash(stringArgOr(call, 1, "HmacSHA256"), []byte(stringArgOr(call, 2, "")))
|
||||
if err != nil {
|
||||
bridgeErr("HMacBase64", err)
|
||||
}
|
||||
h.Write([]byte(stringArg(call, 0)))
|
||||
return vm.ToValue(base64.StdEncoding.EncodeToString(h.Sum(nil)))
|
||||
})
|
||||
|
||||
// ── 其他 ──
|
||||
set("log", func(call goja.FunctionCall) goja.Value {
|
||||
if r.cfg.Log != nil {
|
||||
r.cfg.Log(call.Arguments[0].String())
|
||||
}
|
||||
return goja.Null()
|
||||
})
|
||||
set("getWebViewUA", func(call goja.FunctionCall) goja.Value {
|
||||
return vm.ToValue(defaultWebViewUA)
|
||||
})
|
||||
set("t2s", func(call goja.FunctionCall) goja.Value { return vm.ToValue(stringArg(call, 0)) })
|
||||
set("s2t", func(call goja.FunctionCall) goja.Value { return vm.ToValue(stringArg(call, 0)) })
|
||||
set("htmlFormat", func(call goja.FunctionCall) goja.Value { return vm.ToValue(stringArg(call, 0)) })
|
||||
unsupported := func(name string) func(goja.FunctionCall) goja.Value {
|
||||
return func(call goja.FunctionCall) goja.Value {
|
||||
panic(vm.ToValue("java." + name + " 需要浏览器或本地文件能力,服务端不支持"))
|
||||
}
|
||||
}
|
||||
for _, name := range []string{
|
||||
"webView", "webViewGetSource", "webViewGetOverrideUrl",
|
||||
"startBrowser", "startBrowserAwait", "openVideoPlayer", "getVerificationCode",
|
||||
"importScript", "cacheFile", "downloadFile", "readFile", "readTxtFile", "deleteFile",
|
||||
"unzipFile", "un7zFile", "unrarFile", "unArchiveFile", "getTxtInFolder",
|
||||
"getZipStringContent", "getZipByteArrayContent",
|
||||
"getRarStringContent", "get7zStringContent",
|
||||
} {
|
||||
set(name, unsupported(name))
|
||||
}
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
const defaultWebViewUA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36"
|
||||
|
||||
func md5Hex(s string, short bool) string {
|
||||
sum := md5.Sum([]byte(s))
|
||||
h := hex.EncodeToString(sum[:])
|
||||
if short {
|
||||
return h[8:24]
|
||||
}
|
||||
return h
|
||||
}
|
||||
|
||||
func digestHash(algorithm string) (hash.Hash, error) {
|
||||
switch strings.ToUpper(strings.NewReplacer("-", "", "_", "").Replace(algorithm)) {
|
||||
case "MD5":
|
||||
return md5.New(), nil
|
||||
case "SHA1":
|
||||
return sha1.New(), nil
|
||||
case "SHA256":
|
||||
return sha256.New(), nil
|
||||
case "SHA384":
|
||||
return sha512.New384(), nil
|
||||
case "SHA512":
|
||||
return sha512.New(), nil
|
||||
default:
|
||||
return nil, fmt.Errorf("不支持的摘要算法: %s", algorithm)
|
||||
}
|
||||
}
|
||||
|
||||
func hmacHash(algorithm string, key []byte) (hash.Hash, error) {
|
||||
switch strings.ToLower(strings.NewReplacer("-", "", "_", "").Replace(algorithm)) {
|
||||
case "hmacmd5":
|
||||
return hmac.New(md5.New, key), nil
|
||||
case "hmacsha1":
|
||||
return hmac.New(sha1.New, key), nil
|
||||
case "hmacsha256":
|
||||
return hmac.New(sha256.New, key), nil
|
||||
case "hmacsha512":
|
||||
return hmac.New(sha512.New, key), nil
|
||||
default:
|
||||
return nil, fmt.Errorf("不支持的 HMAC 算法: %s", algorithm)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user