package public import ( "bytes" "crypto" "crypto/aes" "crypto/cipher" "crypto/hmac" "crypto/md5" "crypto/rand" "crypto/rsa" "crypto/sha1" "crypto/sha256" "crypto/sha512" "crypto/x509" "encoding/base64" "encoding/hex" "encoding/json" "encoding/pem" "errors" "fmt" "io" "math" mathRand "math/rand" "net/http" "net/url" "regexp" "strconv" "strings" "time" "unsafe" "golang.org/x/crypto/sha3" "bet24.com/log" "github.com/axgle/mahonia" ) func ConvertToString(src string, srcCode string, tagCode string) string { srcCoder := mahonia.NewDecoder(srcCode) srcResult := srcCoder.ConvertString(src) tagCoder := mahonia.NewEncoder(tagCode) return tagCoder.ConvertString(srcResult) } func GetUtf8(src string) string { return ConvertToString(src, "GB18030", "UTF-8") } func GetGBK(src string) string { return ConvertToString(src, "UTF-8", "GB18030") } const ENCRYPT_KEY_LENGTH = 10 func DecryptDBString(src string) string { lpszIn := []byte(src) if len(lpszIn) >= ENCRYPT_KEY_LENGTH*4 { szSoureLengthBuf := string([]byte{lpszIn[0], lpszIn[1]}) nSoureLength64, _ := strconv.ParseInt(szSoureLengthBuf, 16, 0) nSoureLength := int(nSoureLength64) lpszOut := make([]byte, nSoureLength) for i := 0; i < nSoureLength; i++ { szKeyBuffer := string([]byte{lpszIn[i*4], lpszIn[i*4+1]}) szEncryptBuffer := string([]byte{lpszIn[i*4+2], lpszIn[i*4+3]}) uKey64, _ := strconv.ParseInt(szKeyBuffer, 16, 0) uEncrypt64, _ := strconv.ParseInt(szEncryptBuffer, 16, 0) uKey := uint8(uKey64) uEncrypt := uint8(uEncrypt64) lpszOut[i] = uKey ^ uEncrypt } return string(lpszOut) } return src } func StringIpToInt(ipstring string) uint32 { ipSegs := strings.Split(ipstring, ".") var ipInt int = 0 var pos uint = 0 for _, ipSeg := range ipSegs { tempInt, _ := strconv.Atoi(ipSeg) tempInt = tempInt << pos ipInt = ipInt + tempInt pos += 8 } //fmt.Println("StringIpToInt", ipstring, ipInt) return uint32(ipInt) } func IpIntToString(ipInt uint32) string { ipSegs := make([]string, 4) var len int = len(ipSegs) buffer := bytes.NewBufferString("") for i := 0; i < len; i++ { tempInt := ipInt & 0xFF ipSegs[len-i-1] = strconv.Itoa(int(tempInt)) ipInt = ipInt >> 8 } for i := 0; i < len; i++ { buffer.WriteString(ipSegs[i]) if i < len-1 { buffer.WriteString(".") } } return buffer.String() } // md5加密方式 func GetMd5String(s string) string { h := md5.New() h.Write([]byte(s)) return hex.EncodeToString(h.Sum(nil)) } func HmacSHA1(key string, data string) string { mac := hmac.New(sha1.New, []byte(key)) mac.Write([]byte(data)) return hex.EncodeToString(mac.Sum(nil)) } func HmacSHA256(key, data string) string { mac := hmac.New(sha256.New, []byte(key)) mac.Write([]byte(data)) return hex.EncodeToString(mac.Sum(nil)) } func SHA256(data string) string { hash := sha256.New() hash.Write([]byte(data)) hashed := hash.Sum(nil) return hex.EncodeToString(hashed) } func HmacSHA512(key, data string) string { mac := hmac.New(sha512.New, []byte(key)) mac.Write([]byte(data)) return hex.EncodeToString(mac.Sum(nil)) } func Hmac_SHA3_SHA512(key, data string) string { mac := hmac.New(sha3.New512, []byte(key)) mac.Write([]byte(data)) return hex.EncodeToString(mac.Sum(nil)) } // base64编码 func Base64EncodeStr(src string) string { return string(base64.StdEncoding.EncodeToString([]byte(src))) } // base64解码 func Base64DecodeStr(src string) string { a, err := base64.StdEncoding.DecodeString(src) if err != nil { return "" } return string(a) } // 加密数据 func AesEncrypt(origData, key []byte) ([]byte, error) { block, err := aes.NewCipher(key) if err != nil { return nil, err } blockSize := block.BlockSize() origData = PKCS5Padding(origData, blockSize) blockMode := cipher.NewCBCEncrypter(block, key[:blockSize]) crypted := make([]byte, len(origData)) blockMode.CryptBlocks(crypted, origData) return crypted, nil } // 解密数据 func AesDecrypt(crypted, key []byte) ([]byte, error) { block, err := aes.NewCipher(key) if err != nil { return nil, err } blockSize := block.BlockSize() blockMode := cipher.NewCBCDecrypter(block, key[:blockSize]) origData := make([]byte, len(crypted)) blockMode.CryptBlocks(origData, crypted) origData = PKCS5UnPadding(origData) return origData, nil } // 加密解密需要数据一定的格式, 如果愿数据不符合要求,需要加一些padding func PKCS5Padding(ciphertext []byte, blockSize int) []byte { padding := blockSize - len(ciphertext)%blockSize padtext := bytes.Repeat([]byte{byte(padding)}, padding) return append(ciphertext, padtext...) } // 加密解密需要数据一定的格式, 如果愿数据不符合要求,需要加一些padding func PKCS5UnPadding(origData []byte) []byte { length := len(origData) unpadding := int(origData[length-1]) return origData[:(length - unpadding)] } // 根据经纬度计算两点之间距离(米) func GetDistance(lat1, lng1, lat2, lng2 float64) float64 { radius := 6378137.0 //赤道半径 rad := math.Pi / 180.0 lat1 = lat1 * rad lng1 = lng1 * rad lat2 = lat2 * rad lng2 = lng2 * rad theta := lng2 - lng1 dist := math.Acos(math.Sin(lat1)*math.Sin(lat2) + math.Cos(lat1)*math.Cos(lat2)*math.Cos(theta)) return dist * radius } // HttpSMSCode请求并获取返回信息 func HttpSMSCode(number, smsSendMsg, authSecret, smsPostUrl, code string) (string, error) { //发送的验证码短息内容 sendMsg := fmt.Sprintf(smsSendMsg, code) //设置提交数据 data := struct { AuthSecret string `json:"authSecret"` Number string `json:"number"` Sms string `json:"sms"` }{ AuthSecret: authSecret, Number: number, Sms: sendMsg, } buf, _ := json.Marshal(data) msg := string(buf) log.Debug("httpSMSCode data=%s", msg) //请求 body := HttpPostByJson(smsPostUrl, msg) //打印返回文本 return string(body), nil } // HttpSMSSend请求并获取返回信息 func HttpSMSSend(phone, smsSendMsg, smsAppID, smsApiKey, smsPostUrl string) (string, error) { if phone == "" || smsSendMsg == "" || smsAppID == "" || smsApiKey == "" || smsPostUrl == "" { return "空信息", nil } client := http.Client{} // 设置提交数据 data := fmt.Sprintf("account=%v&password=%v&mobile=%v&content=%v", smsAppID, smsApiKey, phone, smsSendMsg) log.Debug("httpPostSMSCode data=%v", data) // 请求 request, err := http.NewRequest("POST", smsPostUrl, strings.NewReader(data)) if err != nil { log.Release("httpPostSMSCode send Request failer err=%v", err) return "", err // handle error } // 设置Content-Type request.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8") response, err := client.Do(request) // 返回 if err != nil { log.Release("httpPostSMSCode client.Do return failer err=%v", err) return "", err } defer response.Body.Close() body, err := io.ReadAll(response.Body) if err != nil { return "", err } // 打印返回文本 log.Debug(string(body)) return string(body), nil } // HttpWithdraw请求提现并获取返回信息 func HttpWithdraw(postUrl, data string) (string, error) { //log.Debug("HttpWithdraw postUrl=%s data=%s", postUrl, data) client := http.Client{} //请求 request, err := http.NewRequest("POST", postUrl, strings.NewReader(data)) //request, err := http.NewRequest("GET", url, nil) if err != nil { log.Release("HttpWithdraw send Request failer err=%v", err) return "", err // handle error } //设置Content-Type request.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8") response, err := client.Do(request) //返回 if err != nil { log.Release("HttpWithdraw client.Do return failer err=%v", err) return "", err } defer response.Body.Close() body, err := io.ReadAll(response.Body) if err != nil { return "", err } //打印返回文本 //log.Debug(string(body)) return string(body), nil } // 检查手机号并返回手机号 func CheckTelValid(tel string) (string, error) { reg := regexp.MustCompile(`^(\()?(\+62|62|0)(\d{2,3})?\)?[ .-]?\d{2,4}[ .-]?\d{2,4}[ .-]?\d{2,4}$`) matchs := reg.FindStringSubmatch(tel) if len(matchs) <= 0 { errString := fmt.Sprintf("tel format fail %s", tel) return "", errors.New(errString) } return tel, nil } func Sha256WithRsa(source, secret string) string { decodeString, err := base64.StdEncoding.DecodeString(secret) if err != nil { panic(err) } private, err := x509.ParsePKCS8PrivateKey(decodeString) if err != nil { panic(err) } //h := crypto.Hash.New(crypto.SHA256) h := sha256.New() h.Write([]byte(source)) hashed := h.Sum(nil) signature, err := rsa.SignPKCS1v15(rand.Reader, private.(*rsa.PrivateKey), crypto.SHA256, hashed) if err != nil { panic(err) } return base64.StdEncoding.EncodeToString(signature) } // 根据SHA256WithRSA算法获取签名对象实例 func VerifyRsaSignBySHA256(content string, sign string, publicKey string) error { publicKeyByte, err := base64.StdEncoding.DecodeString(publicKey) if err != nil { return err } pub, err := x509.ParsePKIXPublicKey(publicKeyByte) if err != nil { return err } hashed := sha256.Sum256([]byte(content)) signature, err := base64.StdEncoding.DecodeString(sign) if err != nil { return err } return rsa.VerifyPKCS1v15(pub.(*rsa.PublicKey), crypto.SHA256, hashed[:], signature) } // 根据SHA1WithRSA算法获取签名对象实例 func VerifyRsaSignBySHA1(content string, sign string, publicKey string) error { publicKeyByte, err := base64.StdEncoding.DecodeString(publicKey) if err != nil { return err } pub, err := x509.ParsePKIXPublicKey(publicKeyByte) if err != nil { return err } hashed := sha1.Sum([]byte(content)) signature, err := base64.StdEncoding.DecodeString(sign) if err != nil { return err } return rsa.VerifyPKCS1v15(pub.(*rsa.PublicKey), crypto.SHA1, hashed[:], signature) } func CheckMobile(phone string) bool { // 匹配规则 // ^1第一位为一 // [345789]{1} 后接一位345789 的数字 // \\d \d的转义 表示数字 {9} 接9位 // $ 结束符 regRuler := "^1[345789]{1}\\d{9}$" // 正则调用规则 reg := regexp.MustCompile(regRuler) // 返回 MatchString 是否匹配 return reg.MatchString(phone) } const ( letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" // 6 bits to represent a letter index letterIdBits = 6 // All 1-bits as many as letterIdBits letterIdMask = 1<= 0; { if remain == 0 { cache, remain = src.Int63(), letterIdMax } if idx := int(cache & letterIdMask); idx < len(letters) { b[i] = letters[idx] i-- } cache >>= letterIdBits remain-- } return *(*string)(unsafe.Pointer(&b)) } // 解密【模拟了Java SHA1PRNG处理】 func Sha1Decrypt(data, key string) (string, error) { dataByte, _ := Hex2bin(data) keys, err := AesSha1prng([]byte(key), 128) if err != nil { return "", err } block, err := aes.NewCipher(generateKey(keys)) if err != nil { return "", err } decrypted := make([]byte, len(dataByte)) size := block.BlockSize() for bs, be := 0, size; bs < len(dataByte); bs, be = bs+size, be+size { block.Decrypt(decrypted[bs:be], dataByte[bs:be]) } decrypted = PKCS5UnPadding(decrypted) return string(decrypted), nil } // 加密【模拟了Java SHA1PRNG处理】 func Sha1Encrypt(data, key []byte) (string, error) { keys, err := AesSha1prng(key, 128) if err != nil { return "", err } block, err := aes.NewCipher(generateKey(keys)) if err != nil { return "", err } data = PKCS5Padding(data, block.BlockSize()) decrypted := make([]byte, len(data)) size := block.BlockSize() for bs, be := 0, size; bs < len(data); bs, be = bs+size, be+size { block.Encrypt(decrypted[bs:be], data[bs:be]) } return Bin2hex(decrypted), nil } // 模拟java SHA1PRNG 处理 func AesSha1prng(keyBytes []byte, encryptLength int) ([]byte, error) { hashs := Sha1(Sha1(keyBytes)) maxLen := len(hashs) realLen := encryptLength / 8 if realLen > maxLen { return nil, errors.New("invalid length") } return hashs[0:realLen], nil } func Sha1(data []byte) []byte { h := sha1.New() h.Write(data) bs := h.Sum(nil) h.Reset() return bs } // 生成密钥 func generateKey(key []byte) (genKey []byte) { genKey = make([]byte, 16) copy(genKey, key) for i := 16; i < len(key); { for j := 0; j < 16 && i < len(key); j, i = j+1, i+1 { genKey[j] ^= key[i] } } return genKey } func Bin2hex(b []byte) string { return base64.StdEncoding.EncodeToString(b) } func Hex2bin(x string) ([]byte, error) { return base64.StdEncoding.DecodeString(x) } // MD5withRSA 签名 func MD5withRSASign(params url.Values, keys string) error { quUrl, err := url.QueryUnescape(params.Encode()) if err != nil { return err } out, err := rsaSignWithMd5(quUrl, keys) if err != nil { return err } params.Add("sign", out) return nil } // 签名开始 func rsaSignWithMd5(data string, prvKey string) (sign string, err error) { //如果密钥是urlSafeBase64的话需要处理下 prvKey = Base64URLDecode(prvKey) keyBytes, err := base64.StdEncoding.DecodeString(prvKey) if err != nil { return "", err } privateKey, err := x509.ParsePKCS8PrivateKey(keyBytes) if err != nil { return "", err } h := md5.New() h.Write([]byte(data)) hash := h.Sum(nil) signature, err := rsa.SignPKCS1v15(rand.Reader, privateKey.(*rsa.PrivateKey), crypto.MD5, hash[:]) if err != nil { return "", err } out := base64.RawURLEncoding.EncodeToString(signature) return out, nil } // 验签(MD5withRSA) func VerifyMD5withRSA(params url.Values, key string) error { sign := params.Get("sign") params.Del("sign") quUrl, _ := url.QueryUnescape(params.Encode()) return rsaVerifySignWithMd5(quUrl, sign, key) } // 验签开始 func rsaVerifySignWithMd5(originalData, signData, pubKey string) error { sign, err := base64.RawURLEncoding.DecodeString(signData) if err != nil { return err } pubKey = Base64URLDecode(pubKey) public, err := base64.StdEncoding.DecodeString(pubKey) if err != nil { return err } pub, err := x509.ParsePKIXPublicKey(public) if err != nil { return err } hash := md5.New() hash.Write([]byte(originalData)) return rsa.VerifyPKCS1v15(pub.(*rsa.PublicKey), crypto.MD5, hash.Sum(nil), sign) } // MD5withRSA 解密 func MD5withRSADecrypt(sign, privateKey string) string { key := chunkSplit(privateKey, 64, "\n") key = fmt.Sprintf("-----BEGIN RSA PRIVATE KEY-----\n%s\n-----END RSA PRIVATE KEY-----", key) decodedBytes, err := base64.StdEncoding.DecodeString(sign) if err != nil { return "" } block, _ := pem.Decode([]byte(key)) if block == nil { return "" } keys, err := x509.ParsePKCS8PrivateKey(block.Bytes) if err != nil { return "" } resCrypto := "" for _, v := range strSplit(string(decodedBytes), 128) { // 使用 RSA 私钥解密密文 plaintext, errs := rsa.DecryptPKCS1v15(rand.Reader, keys.(*rsa.PrivateKey), []byte(v)) if errs != nil { return "" } resCrypto += string(plaintext) } return resCrypto } // 字符串分割密文 func strSplit(s string, chunkSize int) []string { var chunks []string for i := 0; i < len(s); i += chunkSize { end := i + chunkSize if end > len(s) { end = len(s) } chunks = append(chunks, s[i:end]) } return chunks } // 块分割 func chunkSplit(s string, chunkLen int, separator string) string { var result strings.Builder for i := 0; i < len(s); i += chunkLen { end := i + chunkLen if end > len(s) { end = len(s) } result.WriteString(s[i:end]) if end < len(s) { result.WriteString(separator) } } return result.String() } //因为Base64转码后可能包含有+,/,=这些不安全的URL字符串,所以要进行换字符 // '+' -> '-' // '/' -> '_' // '=' -> '' // 字符串长度不足4倍的位补"=" func Base64URLDecode(data string) string { var missing = (4 - len(data)%4) % 4 data += strings.Repeat("=", missing) //字符串长度不足4倍的位补"=" data = strings.Replace(data, "_", "/", -1) data = strings.Replace(data, "-", "+", -1) return data } func Base64UrlSafeEncode(data string) string { safeUrl := strings.Replace(data, "/", "_", -1) safeUrl = strings.Replace(safeUrl, "+", "-", -1) safeUrl = strings.Replace(safeUrl, "=", "", -1) return safeUrl } // 生成码 func GenCode(length int) string { var chars = []byte("ABCDEFGHJKLMNPQRTUVWXYZ123456789") code := make([]byte, length) clen := len(chars) for i := 0; i < length; i++ { index := mathRand.Intn(clen) code[i] = byte(chars[index]) } return string(code) } // SlicePage 分页算法(pageIndex 页索引、pageSize 页大小、nums 总记录数) // exploreList := manager.Mgr.GetExploreList() // // totalCount := len(exploreList) // start, end := public.SlicePage(req.PageIndex, req.PageSize, totalCount) // rsp.RecordCount = totalCount // rsp.List = this.getOwnerList(exploreList[start:end]) func SlicePage(pageIndex, pageSize, nums int) (start, end int) { if pageIndex <= 0 { pageIndex = 1 } if pageSize < 0 { pageSize = 10 } if pageSize > nums { return 0, nums } // 计算起始行 start = (pageIndex - 1) * pageSize // 计算终止行 end = start + pageSize if end > nums { end = nums } if start > end { return 0, 0 } // 起始、终止位置 return start, end }