util/util.go
2024-11-09 00:13:49 +08:00

924 lines
30 KiB
Go

package util
import (
"bytes"
"crypto"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/hmac"
"crypto/md5"
"crypto/rand"
"crypto/rsa"
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
"crypto/x509"
_ "embed"
"encoding/base64"
"encoding/hex"
"encoding/json"
"encoding/pem"
"errors"
"math/big"
"path/filepath"
"runtime"
"strings"
"text/template"
"time"
"apigo.cc/gojs"
"apigo.cc/gojs/goja"
"github.com/ZZMarquis/gm/sm3"
"github.com/ZZMarquis/gm/sm4"
"github.com/ZZMarquis/gm/util"
"github.com/emmansun/gmsm/sm2"
"github.com/emmansun/gmsm/smx509"
"github.com/obscuren/ecies"
"github.com/ssgo/u"
"gopkg.in/yaml.v3"
)
//go:embed util.ts
var utilTS string
//go:embed README.md
var utilMD string
func init() {
obj := map[string]any{
"json": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
if r, err := json.Marshal(args.Arguments[0].Export()); err == nil {
return vm.ToValue(string(r))
} else {
panic(vm.NewGoError(err))
}
},
"jsonP": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
if r, err := json.Marshal(args.Arguments[0].Export()); err == nil {
r1 := bytes.Buffer{}
if err2 := json.Indent(&r1, r, "", " "); err2 == nil {
return vm.ToValue(string(r))
} else {
return vm.ToValue(string(r))
}
} else {
panic(vm.NewGoError(err))
}
},
"unJson": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
var r any
if err := json.Unmarshal(u.Bytes(args.Arguments[0].Export()), &r); err == nil {
return vm.ToValue(r)
} else {
panic(vm.NewGoError(err))
}
},
"yaml": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
if r, err := yaml.Marshal(args.Arguments[0].Export()); err == nil {
return vm.ToValue(string(r))
} else {
panic(vm.NewGoError(err))
}
},
"unYaml": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
var r any
if err := yaml.Unmarshal(u.Bytes(args.Arguments[0].Export()), &r); err == nil {
return vm.ToValue(r)
} else {
panic(vm.NewGoError(err))
}
},
"save": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(2)
filename := args.Str(0)
var data []byte
var err error
if strings.HasSuffix(filename, ".yml") || strings.HasSuffix(filename, ".yaml") {
data, err = yaml.Marshal(args.Any(1))
} else {
data, err = json.Marshal(args.Any(1))
}
if err == nil {
if err = u.WriteFileBytes(gojs.FindPath(vm, filename), data); err != nil {
panic(vm.NewGoError(err))
}
return nil
} else {
panic(vm.NewGoError(err))
}
},
"load": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
filename := args.Str(0)
if data, err := u.ReadFileBytes(gojs.FindPath(vm, filename)); err == nil {
var r any
if strings.HasSuffix(filename, ".yml") || strings.HasSuffix(filename, ".yaml") {
err = yaml.Unmarshal(data, &r)
} else {
err = json.Unmarshal(data, &r)
}
if err == nil {
return vm.ToValue(r)
} else {
panic(vm.NewGoError(err))
}
} else {
panic(vm.NewGoError(err))
}
},
"base64": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
return vm.ToValue(u.Base64(u.Bytes(args.Arguments[0].Export())))
},
"unBase64": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
return vm.ToValue(u.UnBase64(args.Str(0)))
},
"urlBase64": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
return vm.ToValue(u.UrlBase64String(args.Str(0)))
},
"unUrlBase64": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
return vm.ToValue(u.UnUrlBase64(args.Str(0)))
},
"hex": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
return vm.ToValue(hex.EncodeToString(u.Bytes(args.Arguments[0].Export())))
},
"unHex": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
if r, err := hex.DecodeString(args.Str(0)); err == nil {
return vm.ToValue(r)
} else {
panic(vm.NewGoError(err))
}
},
"aes": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(3)
if r, err := u.EncryptAesBytes(u.Bytes(args.Arguments[0].Export()), u.Bytes(args.Arguments[1].Export()), u.Bytes(args.Arguments[2].Export())); err == nil {
return vm.ToValue(r)
} else {
panic(vm.NewGoError(err))
}
},
"unAes": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(3)
if r, err := u.DecryptAesBytes(u.Bytes(args.Arguments[0].Export()), u.Bytes(args.Arguments[1].Export()), u.Bytes(args.Arguments[2].Export())); err == nil {
return vm.ToValue(r)
} else {
panic(vm.NewGoError(err))
}
},
"sm4": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(3)
if r, err := sm4.CBCEncrypt(u.Bytes(args.Arguments[1].Export())[0:16], u.Bytes(args.Arguments[2].Export())[0:16], util.PKCS5Padding(u.Bytes(args.Arguments[0].Export()), 16)); err == nil {
return vm.ToValue(r)
} else {
panic(vm.NewGoError(err))
}
},
"unSM4": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(3)
if r, err := sm4.CBCDecrypt(u.Bytes(args.Arguments[1].Export())[0:16], u.Bytes(args.Arguments[2].Export())[0:16], u.Bytes(args.Arguments[0].Export())); err == nil {
if length := len(r); length > 0 {
if unpadding := int(r[length-1]); length-unpadding >= 0 {
r = util.PKCS5UnPadding(r)
}
}
return vm.ToValue(r)
} else {
panic(vm.NewGoError(err))
}
},
"genECDSA": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm)
var curve elliptic.Curve
switch args.Int(0) {
case 521:
curve = elliptic.P521()
case 384:
curve = elliptic.P384()
default:
curve = elliptic.P256()
}
pri, err := ecdsa.GenerateKey(curve, u.GlobalRand2)
if err != nil {
panic(vm.NewGoError(err))
}
var buf bytes.Buffer
buf.WriteByte(byte(len(pri.X.Bytes())))
buf.Write(pri.X.Bytes())
buf.Write(pri.Y.Bytes())
return vm.ToValue([][]byte{pri.D.Bytes(), buf.Bytes()})
},
"exportECDSAPrivateKey": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
priKey := makeECDSAPriKey(args.Bytes(0))
priBytes, err := x509.MarshalPKCS8PrivateKey(priKey)
if err != nil {
panic(vm.NewGoError(err))
}
pemBytes := pem.EncodeToMemory(&pem.Block{
Type: "PRIVATE KEY",
Bytes: priBytes,
})
return vm.ToValue(string(pemBytes))
},
"exportECDSAPublicKey": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
pubKey := makeECDSAPubKey(args.Bytes(0))
pubBytes, err := x509.MarshalPKIXPublicKey(pubKey)
if err != nil {
panic(vm.NewGoError(err))
}
pemBytes := pem.EncodeToMemory(&pem.Block{
Type: "PUBLIC KEY",
Bytes: pubBytes,
})
return vm.ToValue(string(pemBytes))
},
"importECDSAKey": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
keyText := args.Str(0)
keyType := args.Str(1)
var keyBytes []byte
if strings.Contains(keyText, "-----BEGIN PRIVATE KEY-----") {
keyType = "private"
if block, _ := pem.Decode([]byte(keyText)); block == nil {
panic(vm.NewGoError(errors.New("bad private pem key")))
} else {
keyBytes = block.Bytes
}
} else if strings.Contains(keyText, "-----BEGIN PUBLIC KEY-----") {
keyType = "public"
if block, _ := pem.Decode([]byte(keyText)); block == nil {
panic(vm.NewGoError(errors.New("bad public pem key")))
} else {
keyBytes = block.Bytes
}
} else {
var err error
if keyBytes, err = base64.StdEncoding.DecodeString(keyText); err != nil {
panic(vm.NewGoError(err))
}
}
if keyType == "private" {
if priKey, err := x509.ParsePKCS8PrivateKey(keyBytes); err != nil {
panic(vm.NewGoError(err))
} else {
if ecdsaPriKey, ok := priKey.(*ecdsa.PrivateKey); !ok {
panic(vm.NewGoError(errors.New("bad private key")))
} else {
return vm.ToValue(ecdsaPriKey.D.Bytes())
}
}
} else {
if pubKey, err := x509.ParsePKIXPublicKey(keyBytes); err != nil {
panic(vm.NewGoError(err))
} else {
if ecdsaPubKey, ok := pubKey.(*ecdsa.PublicKey); !ok {
panic(vm.NewGoError(errors.New("bad public key")))
} else {
var buf bytes.Buffer
buf.WriteByte(byte(len(ecdsaPubKey.X.Bytes())))
buf.Write(ecdsaPubKey.X.Bytes())
buf.Write(ecdsaPubKey.Y.Bytes())
return vm.ToValue(buf.Bytes())
}
}
}
},
"signECDSA": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(2)
data := args.Bytes(0)
priKey := makeECDSAPriKey(args.Bytes(1))
r, s, err := ecdsa.Sign(u.GlobalRand1, priKey, u.Sha256(data))
if err != nil {
panic(vm.NewGoError(err))
}
var buf bytes.Buffer
buf.WriteByte(byte(len(r.Bytes())))
buf.Write(r.Bytes())
buf.Write(s.Bytes())
return vm.ToValue(buf.Bytes())
},
"verifyECDSA": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(3)
data := args.Bytes(0)
signature := args.Bytes(1)
pubKey := makeECDSAPubKey(args.Bytes(2))
byteLen := signature[0]
r := new(big.Int)
s := new(big.Int)
r.SetBytes(signature[1 : byteLen+1])
s.SetBytes(signature[byteLen+1:])
return vm.ToValue(ecdsa.Verify(pubKey, u.Sha256(data), r, s))
},
"encryptECDSA": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(2)
data := args.Bytes(0)
pubKey := makeECDSAPubKey(args.Bytes(1))
eciesPubKey := ecies.ImportECDSAPublic(pubKey)
if r, err := ecies.Encrypt(u.GlobalRand1, eciesPubKey, data, nil, nil); err != nil {
panic(vm.NewGoError(err))
} else {
return vm.ToValue(r)
}
},
"decryptECDSA": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(2)
data := args.Bytes(0)
priKey := makeECDSAPriKey(args.Bytes(1))
eciesPriKey := ecies.ImportECDSA(priKey)
if r, err := eciesPriKey.Decrypt(u.GlobalRand1, data, nil, nil); err != nil {
panic(vm.NewGoError(err))
} else {
return vm.ToValue(r)
}
},
"genSM2": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
if pri, err := sm2.GenerateKey(u.GlobalRand2); err == nil {
var buf bytes.Buffer
buf.WriteByte(byte(len(pri.X.Bytes())))
buf.Write(pri.X.Bytes())
buf.Write(pri.Y.Bytes())
return vm.ToValue([][]byte{pri.D.Bytes(), buf.Bytes()})
} else {
panic(vm.NewGoError(err))
}
},
"exportSM2PrivateKey": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
priKey := makePriKey(args.Bytes(0), sm2.P256())
priBytes, err := smx509.MarshalECPrivateKey(priKey)
if err != nil {
panic(vm.NewGoError(err))
}
pemBytes := pem.EncodeToMemory(&pem.Block{
Type: "PRIVATE KEY",
Bytes: priBytes,
})
return vm.ToValue(string(pemBytes))
},
"exportSM2PublicKey": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
pubKey := makePubKey(args.Bytes(0), sm2.P256())
pubBytes, err := smx509.MarshalPKIXPublicKey(pubKey)
if err != nil {
panic(vm.NewGoError(err))
}
pemBytes := pem.EncodeToMemory(&pem.Block{
Type: "PUBLIC KEY",
Bytes: pubBytes,
})
return vm.ToValue(string(pemBytes))
},
"importSM2Key": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
keyText := args.Str(0)
keyType := args.Str(1)
var keyBytes []byte
if strings.Contains(keyText, "-----BEGIN PRIVATE KEY-----") {
keyType = "private"
if block, _ := pem.Decode([]byte(keyText)); block == nil {
panic(vm.NewGoError(errors.New("bad private pem key")))
} else {
keyBytes = block.Bytes
}
} else if strings.Contains(keyText, "-----BEGIN PUBLIC KEY-----") {
keyType = "public"
if block, _ := pem.Decode([]byte(keyText)); block == nil {
panic(vm.NewGoError(errors.New("bad public pem key")))
} else {
keyBytes = block.Bytes
}
} else {
var err error
if keyBytes, err = base64.StdEncoding.DecodeString(keyText); err != nil {
panic(vm.NewGoError(err))
}
}
if keyType == "private" {
if priKey, err := smx509.ParseECPrivateKey(keyBytes); err != nil {
panic(vm.NewGoError(err))
} else {
return vm.ToValue(priKey.D.Bytes())
}
} else {
if pubKey, err := smx509.ParsePKIXPublicKey(keyBytes); err != nil {
panic(vm.NewGoError(err))
} else {
if sm2PubKey, ok := pubKey.(*ecdsa.PublicKey); !ok {
panic(vm.NewGoError(errors.New("bad public key")))
} else {
var buf bytes.Buffer
buf.WriteByte(byte(len(sm2PubKey.X.Bytes())))
buf.Write(sm2PubKey.X.Bytes())
buf.Write(sm2PubKey.Y.Bytes())
return vm.ToValue(buf.Bytes())
}
}
}
},
"signSM2": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(2)
data := args.Bytes(0)
priKey := makePriKey(args.Bytes(1), sm2.P256())
if r, s, err := sm2.SignWithSM2(u.GlobalRand1, priKey, nil, data); err == nil {
var buf bytes.Buffer
buf.WriteByte(byte(len(r.Bytes())))
buf.Write(r.Bytes())
buf.Write(s.Bytes())
return vm.ToValue(buf.Bytes())
} else {
panic(vm.NewGoError(err))
}
},
"verifySM2": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(3)
data := args.Bytes(0)
signature := args.Bytes(1)
pubKey := makePubKey(args.Bytes(2), sm2.P256())
byteLen := signature[0]
r := new(big.Int)
s := new(big.Int)
r.SetBytes(signature[1 : byteLen+1])
s.SetBytes(signature[byteLen+1:])
return vm.ToValue(sm2.VerifyWithSM2(pubKey, nil, data, r, s))
},
"encryptSM2": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(2)
data := args.Bytes(0)
pubKey := makePubKey(args.Bytes(1), sm2.P256())
if r, err := sm2.Encrypt(u.GlobalRand1, pubKey, data, nil); err == nil {
return vm.ToValue(r)
} else {
panic(vm.NewGoError(err))
}
},
"decryptSM2": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(2)
data := args.Bytes(0)
priKey := makePriKey(args.Bytes(1), sm2.P256())
if r, err := sm2.Decrypt(&sm2.PrivateKey{PrivateKey: *priKey}, data); err == nil {
return vm.ToValue(r)
} else {
panic(vm.NewGoError(err))
}
},
"genRSA": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm)
size := args.Int(0)
if size == 0 {
size = 2048
}
key, err := rsa.GenerateKey(rand.Reader, size)
if err != nil {
panic(vm.NewGoError(err))
}
priBytes := x509.MarshalPKCS1PrivateKey(key)
pubBytes := x509.MarshalPKCS1PublicKey(&key.PublicKey)
return vm.ToValue([][]byte{priBytes, pubBytes})
},
"exportRSAPrivateKey": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
priKey := makeRSAPriKey(args.Bytes(0))
priBytes := x509.MarshalPKCS1PrivateKey(priKey)
pemBytes := pem.EncodeToMemory(&pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: priBytes,
})
return vm.ToValue(string(pemBytes))
},
"exportRSAPublicKey": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
pubKey := makeRSAPubKey(args.Bytes(0))
pubBytes := x509.MarshalPKCS1PublicKey(pubKey)
pemBytes := pem.EncodeToMemory(&pem.Block{
Type: "RSA PUBLIC KEY",
Bytes: pubBytes,
})
return vm.ToValue(string(pemBytes))
},
"importRSAKey": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
keyText := args.Str(0)
keyType := args.Str(1)
var keyBytes []byte
if strings.Contains(keyText, "-----BEGIN RSA PRIVATE KEY-----") {
keyType = "private"
if block, _ := pem.Decode([]byte(keyText)); block == nil {
panic(vm.NewGoError(errors.New("bad private pem key")))
} else {
keyBytes = block.Bytes
}
} else if strings.Contains(keyText, "-----BEGIN RSA PUBLIC KEY-----") {
keyType = "public"
if block, _ := pem.Decode([]byte(keyText)); block == nil {
panic(vm.NewGoError(errors.New("bad public pem key")))
} else {
keyBytes = block.Bytes
}
} else {
var err error
if keyBytes, err = base64.StdEncoding.DecodeString(keyText); err != nil {
panic(vm.NewGoError(err))
}
}
if keyType == "private" {
if priKey, err := x509.ParsePKCS1PrivateKey(keyBytes); err != nil {
panic(vm.NewGoError(err))
} else {
return vm.ToValue(x509.MarshalPKCS1PrivateKey(priKey))
}
} else {
if pubKey, err := x509.ParsePKCS1PublicKey(keyBytes); err != nil {
panic(vm.NewGoError(err))
} else {
return vm.ToValue(x509.MarshalPKCS1PublicKey(pubKey))
}
}
},
"signRSA": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(2)
data := args.Bytes(0)
priKey := makeRSAPriKey(args.Bytes(1))
signature, err := rsa.SignPKCS1v15(rand.Reader, priKey, crypto.SHA256, u.Sha256(data))
if err != nil {
panic(vm.NewGoError(err))
}
return vm.ToValue(signature)
},
"verifyRSA": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(3)
data := args.Bytes(0)
signature := args.Bytes(1)
pubKey := makeRSAPubKey(args.Bytes(2))
err := rsa.VerifyPKCS1v15(pubKey, crypto.SHA256, u.Sha256(data), signature)
return vm.ToValue(err == nil)
},
"encryptRSA": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(2)
data := args.Bytes(0)
pubKey := makeRSAPubKey(args.Bytes(1))
encryptedData, err := rsa.EncryptOAEP(sha256.New(), rand.Reader, pubKey, data, nil)
if err != nil {
panic(vm.NewGoError(err))
}
return vm.ToValue(encryptedData)
},
"decryptRSA": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(2)
data := args.Bytes(0)
priKey := makeRSAPriKey(args.Bytes(1))
decryptedData, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, priKey, data, nil)
if err != nil {
panic(vm.NewGoError(err))
}
return vm.ToValue(decryptedData)
},
"gzip": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
if r, err := u.Gzip(u.Bytes(args.Arguments[0].Export())); err == nil {
return vm.ToValue(r)
} else {
panic(vm.NewGoError(err))
}
},
"gunzip": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
if r, err := u.Gunzip(u.Bytes(args.Arguments[0].Export())); err == nil {
return vm.ToValue(r)
} else {
panic(vm.NewGoError(err))
}
},
"id": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
return vm.ToValue(u.Id12())
},
"uniqueId": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
return vm.ToValue(u.UniqueId())
},
"token": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
size := 20
if len(argsIn.Arguments) > 0 {
size = u.Int(argsIn.Arguments[0].Export())
}
return vm.ToValue(u.MakeToken(size))
},
"md5": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
hash := md5.New()
for _, v := range args.Array(0) {
hash.Write(u.Bytes(v))
}
return vm.ToValue(hash.Sum(nil))
},
"sha1": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
hash := sha1.New()
for _, v := range args.Array(0) {
hash.Write(u.Bytes(v))
}
return vm.ToValue(hash.Sum(nil))
},
"sha256": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
hash := sha256.New()
for _, v := range args.Array(0) {
hash.Write(u.Bytes(v))
}
return vm.ToValue(hash.Sum(nil))
},
"sha512": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
hash := sha512.New()
for _, v := range args.Array(0) {
hash.Write(u.Bytes(v))
}
return vm.ToValue(hash.Sum(nil))
},
"sm3": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
hash := sm3.New()
for _, v := range args.Array(0) {
hash.Write(u.Bytes(v))
}
return vm.ToValue(hash.Sum(nil))
},
"hmacMD5": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(2)
hash := hmac.New(md5.New, args.Bytes(0))
for _, v := range args.Array(1) {
hash.Write(u.Bytes(v))
}
return vm.ToValue(hash.Sum(nil))
},
"hmacSHA1": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(2)
hash := hmac.New(sha1.New, args.Bytes(0))
for _, v := range args.Array(1) {
hash.Write(u.Bytes(v))
}
return vm.ToValue(hash.Sum(nil))
},
"hmacSHA256": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(2)
hash := hmac.New(sha256.New, args.Bytes(0))
for _, v := range args.Array(1) {
hash.Write(u.Bytes(v))
}
return vm.ToValue(hash.Sum(nil))
},
"hmacSHA512": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(2)
hash := hmac.New(sha512.New, args.Bytes(0))
for _, v := range args.Array(1) {
hash.Write(u.Bytes(v))
}
return vm.ToValue(hash.Sum(nil))
},
"hmacSM3": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(2)
hash := hmac.New(sm3.New, args.Bytes(0))
for _, v := range args.Array(1) {
hash.Write(u.Bytes(v))
}
return vm.ToValue(hash.Sum(nil))
},
"tpl": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(2)
var functions = map[string]any{}
if len(argsIn.Arguments) > 2 {
obj := argsIn.Arguments[2].ToObject(vm)
for _, k := range obj.Keys() {
v := obj.Get(k)
if cb, ok := goja.AssertFunction(v); ok {
functions[k] = func(in string) string {
if r, err := cb(argsIn.This, vm.ToValue(in)); err == nil {
return r.String()
}
return ""
}
}
}
}
buf := bytes.NewBuffer(make([]byte, 0))
var err error
tpl := template.New("tpl")
if len(functions) > 0 {
tpl.Funcs(functions)
}
if tpl, err = tpl.Parse(args.Str(0)); err == nil {
err = tpl.Execute(buf, args.Arguments[1].Export())
}
if err != nil {
panic(vm.NewGoError(err))
}
return vm.ToValue(buf.String())
},
"sleep": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
time.Sleep(time.Duration(args.Int64(0)) * time.Millisecond)
return nil
},
"setTimeout": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
callback := args.Func(0)
timeout := time.Duration(args.Int64(1)) * time.Millisecond
if callback != nil {
go func() {
if timeout > 0 {
time.Sleep(timeout)
}
if _, err := callback(args.This, args.Arguments[2:]...); err != nil {
args.Logger.Error(err.Error())
}
}()
}
return nil
},
"shell": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
a := make([]string, len(args.Arguments)-1)
for i := 1; i < len(args.Arguments); i++ {
a[i-1] = args.Str(i)
}
if r, err := u.RunCommand(args.Str(0), a...); err == nil {
return vm.ToValue(r)
} else {
panic(vm.NewGoError(err))
}
},
"toDatetime": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
return vm.ToValue(time.UnixMilli(args.Int64(0)).Format("2006-01-02 15:04:05"))
},
"fromDatetime": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
timeStr := args.Str(0)
if len(timeStr) > 19 {
timeStr = timeStr[0:19]
}
if strings.ContainsRune(timeStr, 'T') {
timeStr = strings.ReplaceAll(timeStr, "T", " ")
}
if tm, err := time.ParseInLocation("2006-01-02 15:04:05", timeStr, time.Local); err == nil {
return vm.ToValue(tm.UnixMilli())
} else {
panic(vm.NewGoError(err))
}
},
"toDate": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
return vm.ToValue(time.UnixMilli(args.Int64(0)).Format("2006-01-02"))
},
"fromDate": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
timeStr := args.Str(0)
if len(timeStr) > 10 {
timeStr = timeStr[0:10]
}
if tm, err := time.ParseInLocation("2006-01-02", timeStr, time.Local); err == nil {
return vm.ToValue(tm.UnixMilli())
} else {
panic(vm.NewGoError(err))
}
},
"os": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
return vm.ToValue(runtime.GOOS)
},
"arch": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
return vm.ToValue(runtime.GOARCH)
},
"joinPath": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
return vm.ToValue(filepath.Join(args.StrArray(0)...))
},
"getPathDir": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
return vm.ToValue(filepath.Dir(args.Str(0)))
},
"getPathBase": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
return vm.ToValue(filepath.Base(args.Str(0)))
},
"getPathVolume": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
return vm.ToValue(filepath.VolumeName(args.Str(0)))
},
"absPath": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
r, err := filepath.Abs(args.Str(0))
if err != nil {
panic(vm.NewGoError(err))
}
return vm.ToValue(r)
},
"cleanPath": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
return vm.ToValue(filepath.Clean(args.Str(0)))
},
"isLocalPath": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
return vm.ToValue(filepath.IsLocal(args.Str(0)))
},
"string": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
return vm.ToValue(u.String(args.Any(0)))
},
"int": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
return vm.ToValue(u.Int64(args.Any(0)))
},
"float": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
return vm.ToValue(u.Float64(args.Any(0)))
},
"bytes": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
return vm.ToValue(u.Bytes(args.Any(0)))
},
"bool": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1)
return vm.ToValue(u.Bool(args.Any(0)))
},
}
gojs.Register("apigo.cc/gojs/util", gojs.Module{
Object: obj,
TsCode: utilTS,
Example: utilMD,
})
}
func makeECDSAPriKey(priKey []byte) *ecdsa.PrivateKey {
if len(priKey) >= 60 {
return makePriKey(priKey, elliptic.P521())
} else if len(priKey) >= 40 {
return makePriKey(priKey, elliptic.P384())
} else {
return makePriKey(priKey, elliptic.P256())
}
}
func makeECDSAPubKey(pubKey []byte) *ecdsa.PublicKey {
if len(pubKey) >= 130 {
return makePubKey(pubKey, elliptic.P521())
} else if len(pubKey) >= 90 {
return makePubKey(pubKey, elliptic.P384())
} else {
return makePubKey(pubKey, elliptic.P256())
}
}
func makePriKey(priKey []byte, curve elliptic.Curve) *ecdsa.PrivateKey {
x, y := curve.ScalarBaseMult(priKey)
return &ecdsa.PrivateKey{
D: new(big.Int).SetBytes(priKey),
PublicKey: ecdsa.PublicKey{
Curve: curve,
X: x,
Y: y,
},
}
}
func makePubKey(pubKey []byte, curve elliptic.Curve) *ecdsa.PublicKey {
keyLen := pubKey[0]
x := new(big.Int)
y := new(big.Int)
x.SetBytes(pubKey[1 : keyLen+1])
y.SetBytes(pubKey[keyLen+1:])
return &ecdsa.PublicKey{Curve: curve, X: x, Y: y}
}
func makeRSAPriKey(keyBytes []byte) *rsa.PrivateKey {
priKey, err := x509.ParsePKCS1PrivateKey(keyBytes)
if err != nil {
return nil
}
return priKey
}
func makeRSAPubKey(keyBytes []byte) *rsa.PublicKey {
pubKey, err := x509.ParsePKCS1PublicKey(keyBytes)
if err != nil {
return nil
}
return pubKey
}