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" "os" "path/filepath" "regexp" "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 var envConfigs map[string]map[string]any var confAes = u.NewAes([]byte("?GQ$0K0GgLdO=f+~L68PLm$uhKr4'=tV"), []byte("VFs7@sK61cj^f?HZ")) var keysIsSet = false func SetSSKey(key, iv []byte) { if !keysIsSet { confAes = u.NewAes(key, iv) keysIsSet = true } } 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)) } }, "uniqueId": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { args := gojs.MakeArgs(&argsIn, vm) size := args.Int(0) var id string if size >= 20 { id = u.UniqueId() } else if size >= 16 { id = u.UniqueId()[0:16] } else if size >= 14 { id = u.ShortUniqueId() } else if size >= 12 { id = u.ShortUniqueId()[0:12] } else { id = u.UniqueId() } return vm.ToValue(id) }, "uniqueIdL": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { args := gojs.MakeArgs(&argsIn, vm) size := args.Int(0) var id string if size >= 20 { id = u.UniqueId() } else if size >= 16 { id = u.UniqueId()[0:16] } else if size >= 14 { id = u.ShortUniqueId() } else if size >= 12 { id = u.ShortUniqueId()[0:12] } else { id = u.UniqueId() } return vm.ToValue(strings.ToLower(id)) }, "id": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { args := gojs.MakeArgs(&argsIn, vm) size := args.Int(0) var id string if size >= 12 { id = u.Id12() } else if size >= 10 { id = u.Id10() } else if size >= 8 { id = u.Id8() } else { id = u.Id6() } return vm.ToValue(id) }, "idL": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { args := gojs.MakeArgs(&argsIn, vm) size := args.Int(0) var id string if size >= 12 { id = u.Id12() } else if size >= 10 { id = u.Id10() } else if size >= 8 { id = u.Id8() } else { id = u.Id6() } return vm.ToValue(strings.ToLower(id)) }, "token": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { args := gojs.MakeArgs(&argsIn, vm) size := args.Int(0) if size == 0 { size = 20 } 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)) } }, "formatDate": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { args := gojs.MakeArgs(&argsIn, vm).Check(1) format := args.Str(0) var tm time.Time if timestamp := args.Int64(1); timestamp > 0 { if timestamp < 10000000000 { timestamp *= 1000 } tm = time.UnixMilli(timestamp) } else { tm = time.Now() } return vm.ToValue(tm.Format(format)) }, "timestampMS": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { return vm.ToValue(time.Now().UnixMilli()) }, "timestamp": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { return vm.ToValue(time.Now().Unix()) }, "toDatetime": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { args := gojs.MakeArgs(&argsIn, vm) var tm time.Time if timestamp := args.Int64(0); timestamp > 0 { if timestamp < 10000000000 { timestamp *= 1000 } tm = time.UnixMilli(timestamp) } else { tm = time.Now() } return vm.ToValue(tm.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) var tm time.Time if timestamp := args.Int64(0); timestamp > 0 { if timestamp < 10000000000 { timestamp *= 1000 } tm = time.UnixMilli(timestamp) } else { tm = time.Now() } return vm.ToValue(tm.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))) }, "searchFile": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { args := gojs.MakeArgs(&argsIn, vm).Check(1) filename := args.Str(0) searchPath := args.Str(1) findFile := "" if searchPath != "" { findFile = searchFile(searchPath, filename) } else { findFile = searchFileFromCurrent(vm, filename) } return vm.ToValue(findFile) }, "loadConfig": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { if envConfigs == nil { envConfigs = map[string]map[string]any{} envFile := searchFileFromCurrent(vm, "env.yml") if envFile == "" { envFile = searchFileFromCurrent(vm, "env.json") } if envFile != "" { u.LoadX(envFile, &envConfigs) } } args := gojs.MakeArgs(&argsIn, vm).Check(1) confName := args.Str(0) conf := map[string]any{} confFile := searchFileFromCurrent(vm, confName+".yml") if confFile == "" { confFile = searchFileFromCurrent(vm, confName+".json") } if confFile != "" { u.LoadX(confFile, &conf) } if envConf, ok := envConfigs[confName]; ok { u.Convert(envConf, &conf) } decTimes := 0 confStr := encryptdMatcher.ReplaceAllStringFunc(u.Json(conf), func(str string) string { if buf, err := base64.URLEncoding.DecodeString(str[1 : len(str)-1]); err == nil { if buf1, err1 := confAes.DecryptBytes(buf); err1 == nil && len(buf1) > 0 { decTimes++ return "\"" + string(buf1) + "\"" } } return str }) if decTimes > 0 { u.UnJson(confStr, &conf) } return vm.ToValue(conf) }, } gojs.Register("apigo.cc/gojs/util", gojs.Module{ Object: obj, TsCode: utilTS, Example: utilMD, SetSSKey: SetSSKey, JsCode: ` $MOD$.keysBy = function (obj, ...fieldAndValues) { let keys = [] for (let k in obj) { let match = true if (fieldAndValues.length === 1) { // 查找一位数组 if (obj[k] != fieldAndValues[0]) { match = false } } else { // 查找二维数组 for (let i = 0; i < fieldAndValues.length; i += 2) { if (obj[k][fieldAndValues[i]] != fieldAndValues[i + 1]) { match = false break } } } if (match) { keys.push(k) } } return keys } $MOD$.countBy = function (obj, ...fieldAndValues) { let keys = $MOD$.keysBy(obj, ...fieldAndValues) l(obj, keys) return keys.length } $MOD$.listBy = function (obj, ...fieldAndValues) { let list = obj instanceof Array || obj instanceof NodeList ? [] : {} let keys = $MOD$.keysBy(obj, ...fieldAndValues) for (let k of keys) { if (obj instanceof Array || obj instanceof NodeList) { list.push(obj[k]) } else { list[k] = obj[k] } } return list } $MOD$.hasBy = function (obj, ...fieldAndValues) { let keys = $MOD$.keysBy(obj, ...fieldAndValues) return keys.length > 0 } $MOD$.getBy = function (obj, ...fieldAndValues) { let keys = $MOD$.keysBy(obj, ...fieldAndValues) if (keys.length > 0) return obj[keys[0]] return null } $MOD$.setBy = function (obj, value, ...fieldAndValues) { let keys = $MOD$.keysBy(obj, ...fieldAndValues) if (keys.length > 0) obj[keys[0]] = value } $MOD$.indexBy = function (obj, ...fieldAndValues) { let keys = $MOD$.keysBy(obj, ...fieldAndValues) if (keys.length > 0) { return obj instanceof Array || obj instanceof NodeList ? $MOD$.int(keys[0]) : keys[0] } return -1 } $MOD$.removeBy = function (obj, ...fieldAndValues) { let keys = $MOD$.keysBy(obj, ...fieldAndValues) let n = 0 for (let i = keys.length - 1; i >= 0; i--) { let k = keys[i] if (obj instanceof Array || obj instanceof NodeList) { obj.splice(k, 1) } else { delete obj[k] } n++ } return n } $MOD$.removeArrayItem = function (list, item) { let pos = list.indexOf(item) if (pos !== -1) list.splice(pos, 1) } $MOD$.last = function (arr) { if (arr && arr.length) { return arr[arr.length - 1] } return null } $MOD$.len = function (obj) { if (obj instanceof Array || obj instanceof NodeList) { return obj.length } else { let n = 0 for (let k in obj) n++ return n } } $MOD$.mergeBy = function (olds, news, ...fields) { if (!olds) return news for (let newItem of news) { let fieldAndValues = [] for (let field of fields) { fieldAndValues.push(field, newItem[field]) } let oldIndex = $MOD$.indexBy(olds, ...fieldAndValues) if (oldIndex === -1) { olds.push(newItem) } else { olds[oldIndex] = newItem } } return olds } $MOD$.sortBy = function (obj, field, isReverse = false, sortType) { let list = obj instanceof Array || obj instanceof NodeList ? [] : {} let sortedKeys = {} let sortArr = [] for (let k in obj) { let v = '' if (field instanceof Array) { for (let f of field) v += obj[k][f] } else { v = obj[k][field] } if (!sortedKeys[v]) { sortedKeys[v] = true sortArr.push(v) } } sortArr.sort((a, b) => { if (sortType === 'int') { a = $MOD$.int(a) b = $MOD$.int(b) } else if (sortType === 'float') { a = $MOD$.float(a) b = $MOD$.float(b) } if (a == b) return 0 if (typeof a === 'number' && typeof b === 'number') { return isReverse ? b - a : a - b } else { return (isReverse ? a < b : a > b) ? 1 : -1 } }) for (let sortKey of sortArr) { for (let k in obj) { let v = '' if (field instanceof Array) { for (let f of field) v += obj[k][f] } else { v = obj[k][field] } if (obj instanceof Array || obj instanceof NodeList) { if (v == sortKey) list.push(obj[k]) } else { if (v == sortKey) list[k] = obj[k] } } } return list } $MOD$.in = function (v1, v2) { if (!(v1 instanceof Array)) v1 = $MOD$.split(v1, /,\s*/) return v1.indexOf(String(v2)) !== -1 } $MOD$.uniquePush = function (arr, ...values) { for (let v of values) { if (arr.indexOf(v) === -1) arr.push(v) } } $MOD$.clearEmpty = function (arr) { let a = [] for (let v of arr) if (v) a.push(v) return a } $MOD$.split = function (v1, v2, n) { let a = $MOD$.str(v1).split(v2) if (!n || n < a.length - 1) return a let a2 = a.slice(0, n) a2[n - 1] = a.slice(n - 1).join(v2) return a2 } $MOD$.splitWithoutEmpty = function (v1, v2, n) { let a = $MOD$.clearEmpty($MOD$.str(v1).split(v2)) if (!n || n < a.length - 1) return a let a2 = a.slice(0, n) a2[n - 1] = a.slice(n - 1).join(v2) return a2 } $MOD$.joinWithoutEmpty = function (arr, separator) { return $MOD$.clearEmpty(arr).join(separator) } $MOD$.makeDefault = function (item, defaults) { for (let k in defaults) { if (!item[k]) item[k] = defaults[k] } } $MOD$._copy = function (obj, isDeepCopy) { let newObj if (obj instanceof Array || obj instanceof NodeList) { newObj = [] for (let o of obj) { if (isDeepCopy && typeof o === 'object' && o) o = $MOD$.copy(o) newObj.push(o) } } else { newObj = {} for (let k in obj) { let v = obj[k] if (isDeepCopy && typeof v === 'object' && v) v = $MOD$.copy(v) newObj[k] = v } } return newObj } $MOD$.copy = function (obj) { return $MOD$._copy(obj, false) } $MOD$.deepCopy = function (obj) { return $MOD$._copy(obj, true) } $MOD$.isNumber = function (v) { const numberMatcher = /^\d*\.?\d+$/ if (typeof v === 'number' || v instanceof Number) return true if (typeof v === 'string') return numberMatcher.test(v) if (typeof v === 'object' && v.toString) numberMatcher.test(v.toString()) return false } $MOD$.isInt = function (v) { const intMatcher = /^\d+$/ if (typeof v === 'number' || v instanceof Number) return $MOD$.int(v) === v if (typeof v === 'string') return intMatcher.test(v) if (typeof v === 'object' && v.toString) intMatcher.test(v.toString()) return false } $MOD$.isFloat = function (v) { const floatMatcher = /^\d*\.\d+$/ if (typeof v === 'float' || v instanceof Number) return $MOD$.int(v) !== v if (typeof v === 'string') return floatMatcher.test(v) if (typeof v === 'object' && v.toString) floatMatcher.test(v.toString()) return false } $MOD$.getByKey = function (obj, ...keys) { let o = {} for (let k in obj) { if (keys.indexOf(k) >= 0) { o[k] = obj[k] } } return o } `, }) } var encryptdMatcher = regexp.MustCompile(`"([\w-=]+)"`) 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 } func searchFile(searchPath, name string) string { searched := map[string]bool{} return _searchFile(searchPath, name, &searched) } func searchFileFromCurrent(vm *goja.Runtime, name string) string { searched := map[string]bool{} startPath := u.String(vm.GoData["startPath"]) filename := _searchFile(startPath, name, &searched) if filename == "" { currentPath, _ := os.Getwd() filename = _searchFile(currentPath, name, &searched) } return filename } func _searchFile(checkPath, name string, searched *map[string]bool) string { for { if !(*searched)[checkPath] { (*searched)[checkPath] = true filename := filepath.Join(checkPath, name) if u.FileExists(filename) { return filename } } oldPath := checkPath checkPath = filepath.Dir(oldPath) if oldPath == checkPath { return "" } } }