This commit is contained in:
cdle
2023-07-02 18:45:12 +08:00
parent 1cf4c35e0f
commit fe0d580cf4
4 changed files with 459 additions and 156 deletions
+310 -45
View File
@@ -1,39 +1,133 @@
package core package core
import ( import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/hmac" "crypto/hmac"
"crypto/md5" "crypto/md5"
"crypto/sha1" "crypto/sha1"
"crypto/sha256" "crypto/sha256"
"crypto/sha512" "crypto/sha512"
"encoding/base64" "encoding/base64"
"encoding/hex"
"fmt" "fmt"
"hash" "hash"
"github.com/dop251/goja"
) )
type Crypto struct{} func toBytes(v interface{}) []byte {
switch v := v.(type) {
type Hmac struct { case []byte:
Algorithm string return v
hash hash.Hash case string:
return []byte(v)
case *Buffer:
return v.value
}
return nil
} }
func (h *Hmac) Digest(class string) string { func toString(v interface{}) string {
value := h.hash.Sum(nil) switch v := v.(type) {
switch class { case []byte:
case "hex": return string(v)
return fmt.Sprintf("%x", value) case string:
case "base64": return v
return base64.StdEncoding.EncodeToString(value) case *Buffer:
return string(v.value)
} }
return "" return ""
} }
func (h *Hmac) Update(data string) { type Crypto struct {
h.hash.Write([]byte(data)) vm *goja.Runtime
} }
func (c *Crypto) CreateHmac(algorithm, key string) *Hmac { type Hmac struct {
// decode bool
vm *goja.Runtime
Algorithm string
middle interface{}
}
func (h *Hmac) Digest(EF string) interface{} {
var result interface{}
var SF = ""
switch h.Algorithm {
case "md5", "sha1", "sha256", "sha512":
result = h.middle.(hash.Hash).Sum(nil)
case "aes-256-cbc":
}
if EF == "" {
return &Buffer{
value: result.([]byte),
}
}
return Convert(h.vm, result, SF, EF)
}
func (h *Hmac) Update(data interface{}, SF, EF string) interface{} {
switch h.Algorithm {
case "md5", "sha1", "sha256", "sha512":
h.middle.(hash.Hash).Write(toBytes(data))
case "aes-256-cbc":
if SF == "hex" {
data = Convert(h.vm, data, "hex", "")
}
return Convert(h.vm, h.middle.(*AesCipher).Update(toBytes(data)), "", EF)
}
return nil
}
func (h *Hmac) Final(EF string) interface{} {
switch h.Algorithm {
case "md5", "sha1", "sha256", "sha512":
case "aes-256-cbc":
return Convert(h.vm, h.middle.(*AesCipher).Final(), "", EF)
}
return nil
}
func (c *Crypto) CreateCipheriv(algorithm string, key, iv interface{}) *Hmac {
var middle interface{}
var err error
switch algorithm {
case "aes-256-cbc":
middle, err = NewAesCipher(c.vm, toBytes(key), toBytes(iv), false)
if err != nil {
panic(Error(c.vm, err))
}
}
return &Hmac{
vm: c.vm,
// decode: true,
middle: middle,
Algorithm: algorithm,
}
}
func (c *Crypto) CreateDecipheriv(algorithm string, key, iv interface{}) *Hmac {
var middle interface{}
var err error
switch algorithm {
case "aes-256-cbc":
middle, err = NewAesCipher(c.vm, toBytes(key), toBytes(iv), true)
if err != nil {
panic(Error(c.vm, err))
}
}
return &Hmac{
// decode: true,
vm: c.vm,
middle: middle,
Algorithm: algorithm,
}
}
func (c *Crypto) CreateHash(algorithm string) *Hmac {
var hashFunc func() hash.Hash var hashFunc func() hash.Hash
switch algorithm { switch algorithm {
case "md5": case "md5":
@@ -48,28 +142,95 @@ func (c *Crypto) CreateHmac(algorithm, key string) *Hmac {
return nil return nil
} }
return &Hmac{ return &Hmac{
hash: hmac.New(hashFunc, []byte(key)), vm: c.vm,
middle: hashFunc(),
Algorithm: algorithm, Algorithm: algorithm,
} }
} }
// func (c *Crypto) CreateCipheriv(algorithm, key, data string) *Hmac { func (c *Crypto) CreateHmac(algorithm string, key interface{}) *Hmac {
// switch algorithm { var hashFunc func() hash.Hash
// case "aes-256-cbc": switch algorithm {
// block, err := aes.NewCipher([]byte(key)) case "md5":
// if err != nil { hashFunc = md5.New
// return "", err case "sha1":
// } hashFunc = sha1.New
// ciphertext := make([]byte, aes.BlockSize+len(data)) case "sha256":
// iv := ciphertext[:aes.BlockSize] hashFunc = sha256.New
// if _, err := io.ReadFull(rand.Reader, iv); err != nil { case "sha512":
// return "", err hashFunc = sha512.New
// } default:
// stream := cipher.NewCFBEncrypter(block, iv) return nil
// stream.XORKeyStream(ciphertext[aes.BlockSize:], []byte(data)) }
// return base64.StdEncoding.EncodeToString(ciphertext), nil return &Hmac{
// } vm: c.vm,
// } middle: hmac.New(hashFunc, toBytes(key)),
Algorithm: algorithm,
}
}
type AesCipher struct {
block cipher.Block
iv []byte
mode cipher.BlockMode
decode bool
buffer bytes.Buffer
vm *goja.Runtime
}
func NewAesCipher(vm *goja.Runtime, key, iv []byte, decode bool) (*AesCipher, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
mode := cipher.NewCBCDecrypter(block, iv)
if !decode {
mode = cipher.NewCBCEncrypter(block, iv)
}
return &AesCipher{
vm: vm,
block: block,
iv: iv,
mode: mode,
decode: decode,
}, nil
}
func (ac *AesCipher) Update(text []byte) []byte {
//fmt.Println("Update", string(text))
if ac.decode {
// Decrypt
var err error
//fmt.Println("Decrypt1", string(text))
ac.mode.CryptBlocks(text, text)
//fmt.Println("Decrypt2", string(text))
text, err = pkcs7Unpadding(text)
if err != nil {
panic(Error(ac.vm, err))
}
//fmt.Println("Decrypt3", string(text), err)
} else {
// Encrypt
text = pkcs7Padding(text, ac.block.BlockSize())
ac.mode.CryptBlocks(text, text)
}
ac.buffer.Write(text)
return nil
// return text
}
func (ac *AesCipher) Final() []byte {
return ac.buffer.Bytes()
}
func pkcs7Unpadding(data []byte) ([]byte, error) {
length := len(data)
unpadding := int(data[length-1])
if unpadding > length {
return nil, fmt.Errorf("pkcs7: invalid padding")
}
return data[:(length - unpadding)], nil
}
// type Cipher struct{} // type Cipher struct{}
@@ -117,15 +278,119 @@ func (c *Crypto) CreateHmac(algorithm, key string) *Hmac {
// return base64.StdEncoding.EncodeToString(ciphertext), nil // return base64.StdEncoding.EncodeToString(ciphertext), nil
// } // }
// func (c *Cipher) Rc4Decrypt(key, ciphertext string) (string, error) { // func (c *Cipher) Rc4Decrypt(key, ciphertext string) (string, error) {
// cipher, err := rc4.NewCipher([]byte(key)) // cipher, err := rc4.NewCipher([]byte(key))
// if err != nil { // if err != nil {
// return "", err // return "", err
// } // }
// data, err := base64.StdEncoding.DecodeString(ciphertext) // data, err := base64.StdEncoding.DecodeString(ciphertext)
// if err != nil { // if err != nil {
// return "", err // return "", err
// } // }
// cipher.XORKeyStream(data, data) // cipher.XORKeyStream(data, data)
// return string(data), nil // return string(data), nil
// } // }
func Convert(vm *goja.Runtime, data interface{}, fromFormat string, toFormat string) interface{} {
//fmt.Println(data, fromFormat, toFormat)
var dataBytes []byte
switch input := data.(type) {
case string:
dataBytes = []byte(input)
case []byte:
dataBytes = input
case *Buffer:
dataBytes = input.value
default:
panic(Error(vm, fmt.Errorf("invalid data type: %T", data)))
}
switch fromFormat {
case "hex":
// 将数据从 HEX 编码格式转换为字节数组
decodedData, err := hex.DecodeString(string(dataBytes))
if err != nil {
panic(Error(vm, err))
}
dataBytes = decodedData
case "base64":
// 将数据从 Base64 编码格式转换为字节数组
decodedData, err := base64.StdEncoding.DecodeString(string(dataBytes))
if err != nil {
panic(Error(vm, err))
}
dataBytes = decodedData
case "bytes", "binary":
// 不需要进行转换
case "utf8", "utf-8", "":
default:
panic(Error(vm, fmt.Errorf("unsupported input format: %s", fromFormat)))
}
//fmt.Println(string(dataBytes), fromFormat, toFormat)
switch toFormat {
case "hex":
// 将数据转换为 HEX 编码格式
//fmt.Println("hex", hex.EncodeToString(dataBytes), fromFormat, toFormat)
return hex.EncodeToString(dataBytes)
case "base64":
// 将数据转换为 Base64 编码格式
return base64.StdEncoding.EncodeToString(dataBytes)
case "bytes", "binary":
// 不需要进行转换
return dataBytes
case "utf8", "utf-8", "":
// 将数据转换为 UTF-8 编码格式
return string(dataBytes)
default:
panic(Error(vm, fmt.Errorf("unsupported output format: %s", toFormat)))
}
}
// panic: interface conversion: interface {} is *cipher.cfb, not *core.AesCipher [recovered]
// panic: interface conversion: interface {} is *cipher.cfb, not *core.AesCipher
// goroutine 15 [running]:
// github.com/dop251/goja.(*Runtime).RunProgram.func1()
// C:/Users/Administrator/go/pkg/mod/github.com/dop251/goja@v0.0.0-20230605162241-28ee0ee714f3/runtime.go:1491 +0x3b8
// panic({0x1a5f6e0, 0xc0017a4780})
// C:/Program Files/Go/src/runtime/panic.go:884 +0x213
// github.com/dop251/goja.(*vm).handleThrow(0xc001312240, {0x1a5f6e0, 0xc0017a4780})
// C:/Users/Administrator/go/pkg/mod/github.com/dop251/goja@v0.0.0-20230605162241-28ee0ee714f3/vm.go:788 +0x497
// github.com/dop251/goja.(*vm).runTryInner.func1()
// C:/Users/Administrator/go/pkg/mod/github.com/dop251/goja@v0.0.0-20230605162241-28ee0ee714f3/vm.go:830 +0x45
// panic({0x1a5f6e0, 0xc0017a4780})
// C:/Program Files/Go/src/runtime/panic.go:884 +0x213
// github.com/cdle/sillyplus/core.(*Hmac).Final(0x2?, {0xc0008266d4?, 0x1?})
// C:/Users/Administrator/Desktop/sillyplus/core/node_ crypto.go:90 +0x145
// reflect.Value.call({0x1a8dfc0?, 0xc0017a43c0?, 0x1c5efb2f198?}, {0x1b85371, 0x4}, {0xc0009fc060, 0x1, 0x0?})
// C:/Program Files/Go/src/reflect/value.go:586 +0xb0b
// reflect.Value.Call({0x1a8dfc0?, 0xc0017a43c0?, 0xc000f687c0?}, {0xc0009fc060?, 0xc001076630?, 0x0?})
// C:/Program Files/Go/src/reflect/value.go:370 +0xbc
// github.com/dop251/goja.(*Runtime).wrapReflectFunc.func1({{0x2139e58, 0xc0017a43f0}, {0xc000110aa0, 0x1, 0x46}})
// C:/Users/Administrator/go/pkg/mod/github.com/dop251/goja@v0.0.0-20230605162241-28ee0ee714f3/runtime.go:2056 +0x3dc
// github.com/dop251/goja.(*nativeFuncObject).vmCall(0xc001784780, 0xc001312240, 0x1)
// C:/Users/Administrator/go/pkg/mod/github.com/dop251/goja@v0.0.0-20230605162241-28ee0ee714f3/func.go:559 +0x1af
// github.com/dop251/goja.call.exec(0x5?, 0xc001312240)
// C:/Users/Administrator/go/pkg/mod/github.com/dop251/goja@v0.0.0-20230605162241-28ee0ee714f3/vm.go:3366 +0x6a
// github.com/dop251/goja.(*vm).run(0xc001312240)
// C:/Users/Administrator/go/pkg/mod/github.com/dop251/goja@v0.0.0-20230605162241-28ee0ee714f3/vm.go:582 +0x62
// github.com/dop251/goja.(*vm).runTryInner(0x1b16220?)
// C:/Users/Administrator/go/pkg/mod/github.com/dop251/goja@v0.0.0-20230605162241-28ee0ee714f3/vm.go:834 +0x70
// github.com/dop251/goja.(*vm).runTry(0xc001312240)
// C:/Users/Administrator/go/pkg/mod/github.com/dop251/goja@v0.0.0-20230605162241-28ee0ee714f3/vm.go:820 +0x1c9
// github.com/dop251/goja.(*Runtime).RunProgram(0xc000b89c00, 0xc000ef1f20)
// C:/Users/Administrator/go/pkg/mod/github.com/dop251/goja@v0.0.0-20230605162241-28ee0ee714f3/runtime.go:1513 +0x48d
// github.com/cdle/sillyplus/core.initPlugin.func3.1(0xc000b89c00)
// C:/Users/Administrator/Desktop/sillyplus/core/plugin_core.go:585 +0x61d
// github.com/dop251/goja_nodejs/eventloop.(*EventLoop).Run(0xc001583b00, 0xc00126df20)
// C:/Users/Administrator/go/pkg/mod/github.com/dop251/goja_nodejs@v0.0.0-20230602164024-804a84515562/eventloop/eventloop.go:203 +0x37
// github.com/cdle/sillyplus/core.initPlugin.func3({0x2141bb8, 0xc001312120}, 0x0)
// C:/Users/Administrator/Desktop/sillyplus/core/plugin_core.go:511 +0x126
// github.com/cdle/sillyplus/core.AddCommand.func1(0xc000ac1d40)
// C:/Users/Administrator/Desktop/sillyplus/core/function.go:372 +0xcb
// created by github.com/cdle/sillyplus/core.AddCommand
// C:/Users/Administrator/Desktop/sillyplus/core/function.go:369 +0xfe
+130 -100
View File
@@ -6,104 +6,134 @@ import (
"github.com/dop251/goja" "github.com/dop251/goja"
) )
func Buffer(vm *goja.Runtime, call goja.ConstructorCall) *goja.Object { type BufferObj struct {
var buffer []byte vm *goja.Runtime
switch arg := call.Arguments[0].Export().(type) { }
case string:
buffer = []byte(arg) func (b *BufferObj) From(v interface{}, EF string) *Buffer {
case []byte: var buffer []byte
buffer = arg switch v := v.(type) {
case int: case string:
buffer = make([]byte, arg) if EF != "" {
case int64: buffer = Convert(b.vm, v, EF, "bytes").([]byte)
buffer = make([]byte, arg) } else {
default: buffer = []byte(v)
panic(vm.NewTypeError("invalid argument type")) }
} case []byte:
obj := call.This.ToObject(vm) if EF != "" {
obj.Set("length", func() int { buffer = Convert(b.vm, v, EF, "bytes").([]byte)
return len(buffer) } else {
}) buffer = v
}
obj.Set("write", func(value interface{}, offset int, length int) { case int:
var buf []byte buffer = make([]byte, v)
switch value := value.(type) { case int64:
case string: buffer = make([]byte, v)
buf = []byte(value) default:
case []byte: panic(b.vm.NewTypeError("invalid argument type"))
buf = value }
default: return &Buffer{
panic(vm.NewTypeError("invalid argument type")) vm: b.vm,
} value: buffer,
}
if offset+length > len(buffer) { }
panic(vm.NewGoError(errors.New("out of range")))
} func (b *BufferObj) Alloc(v int) *Buffer {
return &Buffer{
copy(buffer[offset:], buf[:length]) vm: b.vm,
}) value: make([]byte, v),
}
obj.Set("toString", func() string { }
return string(buffer)
}) type Buffer struct {
value []byte
obj.Set("slice", func(start int, end int) []byte { vm *goja.Runtime
if start < 0 { }
start += len(buffer)
} func (b *Buffer) Length() int {
if end < 0 { return len(b.value)
end += len(buffer) }
}
if end > len(buffer) { func (b *Buffer) Write(value interface{}, offset int, length int) int {
end = len(buffer) var buf []byte
} switch value := value.(type) {
if start >= end || start >= len(buffer) { case string:
return nil buf = []byte(value)
} case []byte:
return buffer[start:end] buf = value
}) default:
panic(b.vm.NewTypeError("invalid argument type"))
obj.Set("copy", func(target []byte, sourceStart int, targetStart int, sourceEnd int) int { }
if sourceStart < 0 {
sourceStart += len(buffer) if offset+length > len(b.value) {
} panic(b.vm.NewGoError(errors.New("out of range")))
if sourceEnd < 0 { }
sourceEnd += len(buffer) copy(b.value[offset:], buf[:length])
} return len(b.value)
if targetStart < 0 { }
targetStart += len(target)
} func (b *Buffer) ToString(EF string) interface{} {
if sourceEnd > len(buffer) { if EF != "" {
sourceEnd = len(buffer) return Convert(b.vm, b.value, "", EF)
} }
if sourceStart >= sourceEnd || sourceStart >= len(buffer) { return string(b.value)
return 0 }
}
return copy(target[targetStart:], buffer[sourceStart:sourceEnd]) func (b *Buffer) Slice(start int, end int) *Buffer {
}) if start < 0 {
start += len(b.value)
obj.Set("join", func(sep []byte, buffers ...[]byte) []byte { }
var totalLen int if end <= 0 {
for _, buf := range buffers { end += len(b.value)
totalLen += len(buf) }
} if end > len(b.value) {
if len(sep) > 0 && len(buffers) > 1 { end = len(b.value)
totalLen += len(sep) * (len(buffers) - 1) }
} if start >= end || start >= len(b.value) {
return nil
result := make([]byte, totalLen) }
offset := 0 return &Buffer{
for i, buf := range buffers { value: b.value[start:end],
copy(result[offset:], buf) }
offset += len(buf) }
if i < len(buffers)-1 && len(sep) > 0 {
copy(result[offset:], sep) func (b *Buffer) Copy(target []byte, sourceStart int, targetStart int, sourceEnd int) int {
offset += len(sep) if sourceStart < 0 {
} sourceStart += len(b.value)
} }
if sourceEnd < 0 {
return result sourceEnd += len(b.value)
}) }
if targetStart < 0 {
return call.This targetStart += len(target)
}
if sourceEnd > len(b.value) {
sourceEnd = len(b.value)
}
if sourceStart >= sourceEnd || sourceStart >= len(b.value) {
return 0
}
return copy(target[targetStart:], b.value[sourceStart:sourceEnd])
}
func (b *Buffer) Join(sep []byte, buffers ...[]byte) []byte {
var totalLen int
for _, buf := range buffers {
totalLen += len(buf)
}
if len(sep) > 0 && len(buffers) > 1 {
totalLen += len(sep) * (len(buffers) - 1)
}
result := make([]byte, totalLen)
offset := 0
for i, buf := range buffers {
copy(result[offset:], buf)
offset += len(buf)
if i < len(buffers)-1 && len(sep) > 0 {
copy(result[offset:], sep)
offset += len(sep)
}
}
return result
} }
+15 -7
View File
@@ -81,7 +81,13 @@ func CancelPluginlistening(uuid string) {
} }
} }
var debug = sillyGirl.GetBool("debug", false)
func initPlugins() { func initPlugins() {
storage.Watch(sillyGirl, "debug", func(old, new, key string) *storage.Final {
debug = new == "true"
return nil
})
plugins.Foreach(func(key, data []byte) error { plugins.Foreach(func(key, data []byte) error {
f, cbs, err := initPlugin(string(data), string(key)) f, cbs, err := initPlugin(string(data), string(key))
if err != nil { if err != nil {
@@ -497,13 +503,15 @@ func initPlugin(data string, uuid string) (*common.Function, []func(), error) {
f := &common.Function{ f := &common.Function{
Handle: func(s common.Sender, set func(vm *goja.Runtime)) interface{} { Handle: func(s common.Sender, set func(vm *goja.Runtime)) interface{} {
defer func() { if !debug {
err := recover() defer func() {
if err != nil { err := recover()
pluginConsole(uuid).Error("脚本错误:", err) if err != nil {
// s.Reply(fmt.Sprint(err)) pluginConsole(uuid).Error("脚本错误:", err)
} // s.Reply(fmt.Sprint(err))
}() }
}()
}
if err2 != nil { if err2 != nil {
panic(err2) panic(err2)
} }
+4 -4
View File
@@ -347,9 +347,7 @@ func SetPluginMethod(vm *goja.Runtime, uuid string, on_start bool, running func(
// 字符串转Base64编码 // 字符串转Base64编码
vm.Set("stringToBase64", stringToBase64) vm.Set("stringToBase64", stringToBase64)
vm.Set("base64ToString", base64ToString) vm.Set("base64ToString", base64ToString)
vm.Set("Buffer", func(call goja.ConstructorCall) *goja.Object { vm.Set("Buffer", &BufferObj{vm: vm})
return Buffer(vm, call)
})
vm.Set("fetch", func(wts ...interface{}) interface{} { vm.Set("fetch", func(wts ...interface{}) interface{} {
promise, resolve, reject := vm.NewPromise() promise, resolve, reject := vm.NewPromise()
go func() { go func() {
@@ -443,7 +441,9 @@ func SetPluginMethod(vm *goja.Runtime, uuid string, on_start bool, running func(
} }
return nil return nil
}) })
vm.Set("crypto", &Crypto{}) vm.Set("crypto", &Crypto{
vm: vm,
})
} }
func EncryptPlugin(script string) string { func EncryptPlugin(script string) string {