package utils import ( "crypto/aes" "crypto/cipher" "crypto/md5" "crypto/rand" "crypto/sha1" "encoding/base64" "errors" "fmt" "io" "strconv" "strings" "github.com/shirou/gopsutil/disk" "github.com/shirou/gopsutil/net" ) // 字符串生成md5 func CreatMD5(s string) string { data := []byte(s) has := md5.Sum(data) return fmt.Sprintf("%x", has) } func GetDiskId() string { partitions, err := disk.Partitions(false) if err != nil { return "" } return disk.GetDiskSerialNumber(partitions[0].Device) } // 获取物理网卡mac地址 func GetRealMacAddr() string { netInterfaces, err := net.Interfaces() if err != nil { return "" } loindex := 0 for _, netInterface := range netInterfaces { if netInterface.Name == "lo" { loindex = netInterface.Index break } } if len(netInterfaces) < loindex+1 { return "" } fmt.Println(netInterfaces[loindex].HardwareAddr) return netInterfaces[loindex].HardwareAddr } func GetDeviceId() string { // deviceId := fmt.Sprintf("%s:%s", GetRealMacAddr(), GetDiskId()) deviceId := GetRealMacAddr() fmt.Println(deviceId) return CreatMD5(deviceId) } // sha1()方法,返回的是byte转换的字符串,如果需要转成16进制,可以使用hex.EncodeToString func GetSha1(str string) string { h := sha1.New() io.WriteString(h, str) return string(h.Sum(nil)) } // 右边补全字符串实现方法,主要实现php的str_pad()方法 func StrPadRight(input string, padLength int, padString string) string { output := "" inputLen := len(input) if inputLen >= padLength { return input } ll := padLength - inputLen for i := 1; i <= ll; i = i + len(padString) { output += padString } return input + output } // 生成密钥 func GenSecretKey(appId string, appSecret string) (secretKey string) { key := appId + "&" + appSecret sha1_str := GetSha1(key) str10 := "0" pack64, _ := strconv.ParseUint(str10, 10, 32) fmt.Println(pack64) pack32 := uint32(pack64) str_pad := StrPadRight(sha1_str, 32, string(rune(pack32))) secretKey = base64.StdEncoding.EncodeToString([]byte(str_pad)) return secretKey } // 解密 func GetCallbackData(secretKey string, encryptData string) (result_str string, err error) { decodeSecretKeyByte, _ := base64.StdEncoding.DecodeString(secretKey) decodeSecretKey := string(decodeSecretKeyByte) orderSuccessPayInfoByte, err2 := DecodeAesGcm(encryptData, decodeSecretKey, "") result_str = string(orderSuccessPayInfoByte) if err2 != nil { return result_str, errors.New("decode error") } return result_str, err } // 加密 func SetCallbackData(secretKey string, data string) (result_str string, err error) { decodeSecretKeyByte, _ := base64.StdEncoding.DecodeString(secretKey) decodeSecretKey := string(decodeSecretKeyByte) orderSuccessPayInfoByte, err2 := EncodeAesGcm(data, decodeSecretKey, "") result_str = string(orderSuccessPayInfoByte) if err2 != nil { return result_str, errors.New("encode error") } return result_str, err } // url安全模式decode字符串 func UrlSafeB64decode(str string) (result []byte) { str = strings.Replace(str, "-", "+", -1) str = strings.Replace(str, "_", "/", -1) mod4 := len(str) % 4 if mod4 != 0 { str = str + "===="[0:mod4] } result, _ = base64.StdEncoding.DecodeString(str) return result } // base64字符串,替换转换为安全模式 func UrlSafeB64encode(str string) (result string) { str = strings.Replace(str, "+", "-", -1) str = strings.Replace(str, "/", "_", -1) return str } // 使用aes-256-gcm方式解密字符串 func DecodeAesGcm(encryptData string, hex_key string, hex_add string) ([]byte, error) { tagSize := 16 //nonceSize,tag的长度,用于open时候生成tag,默认12 key := []byte(hex_key) add := []byte(hex_add) block, err := aes.NewCipher(key) //生成加解密用的block if err != nil { return []byte(""), err } //根据不同加密算法,也有不同tag长度的方法设定和调用,比如NewGCMWithTagSize、newGCMWithNonceAndTagSize aesgcm, err := cipher.NewGCMWithNonceSize(block, tagSize) if err != nil { return []byte(""), err } decodeEncryptStr := UrlSafeB64decode(encryptData) ciphertext := decodeEncryptStr if len(ciphertext) <= aesgcm.NonceSize() { // 长度应该>iv return []byte(""), errors.New("string: too short") //解密失败 } iv := ciphertext[:aesgcm.NonceSize()] //分离出IV ciphertext = ciphertext[aesgcm.NonceSize():] // 密文,tag是调用open方法时候通过密文和前面new时候传的size来进行截取的 plaintext, err := aesgcm.Open(nil, iv, ciphertext, add) return plaintext, err } // 使用aes-256-gcm加密数据 func EncodeAesGcm(data string, hex_key string, hex_add string) (result string, error error) { tagSize := 16 //nonceSize,tag的长度,用于open时候生成tag,默认12 key := []byte(hex_key) add := []byte(hex_add) block, err := aes.NewCipher(key) //生成加解密用的block if err != nil { return result, err } //根据不同加密算法,也有不同tag长度的方法设定和调用,比如NewGCMWithTagSize、newGCMWithNonceAndTagSize aesgcm, err := cipher.NewGCMWithNonceSize(block, tagSize) if err != nil { return result, err } plaintext := []byte(data) iv := make([]byte, tagSize) // NonceSize=12 rand.Read(iv) //获取随机值 ciphertext := aesgcm.Seal(iv, iv, plaintext, add) //加密,密文为:iv+密文+tag result = base64.StdEncoding.EncodeToString(ciphertext) result = UrlSafeB64encode(result) return result, nil // 生成的BS64 }