package publicmethod import ( "appPlatform/overall" "bytes" "crypto/cipher" "encoding/hex" "fmt" "strings" "github.com/tjfoc/gmsm/sm4" ) /* * @ 作者: 秦东 @ 时间: 2024-08-28 14:51:02 @ 功能: SM4加密 @ 参数 #data 要加密的字符 #key 附加选项 @ 返回值 # @ 方法原型 # */ func SM4Encrypt(data string, key ...string) (string, error) { SM4Key := overall.CONSTANT_CONFIG.Appsetup.AppKey if len(key) > 0 { SM4Key = strings.Join(key, "-") } SM4Key = processString(SM4Key, 16, "s") //字符串转byte切片 plainText := []byte(data) SM4Iv := "04TzMuvkHm_EZnHm" iv := []byte(SM4Iv) keySm4 := []byte(SM4Key) //实例化sm4加密对象 block, err := sm4.NewCipher(keySm4) fmt.Printf("block:%v=====>%v\n", err, string(keySm4)) if err != nil { return "1", err } //明文数据填充 paddingData := paddingLastGroup(plainText, block.BlockSize()) //声明SM4的加密工作模式 blockMode := cipher.NewCBCEncrypter(block, iv) //为填充后的数据进行加密处理 cipherText := make([]byte, len(paddingData)) //使用CryptBlocks这个核心方法,将paddingData进行加密处理,将加密处理后的值赋值到cipherText中 blockMode.CryptBlocks(cipherText, paddingData) //加密结果使用hex转成字符串,方便外部调用 cipherString := hex.EncodeToString(cipherText) return cipherString, nil } // 明文数据填充 func paddingLastGroup(plainText []byte, blockSize int) []byte { //1.计算最后一个分组中明文后需要填充的字节数 padNum := blockSize - len(plainText)%blockSize //2.将字节数转换为byte类型 char := []byte{byte(padNum)} //3.创建切片并初始化 newPlain := bytes.Repeat(char, padNum) //4.将填充数据追加到原始数据后 newText := append(plainText, newPlain...) return newText } // 去掉明文后面的填充数据 func unPaddingLastGroup(plainText []byte) []byte { //1.拿到切片中的最后一个字节 length := len(plainText) lastChar := plainText[length-1] //2.将最后一个数据转换为整数 number := int(lastChar) return plainText[:length-number] } /* * @ 作者: 秦东 @ 时间: 2024-08-28 14:58:03 @ 功能: SM4解密 @ 参数 # @ 返回值 # @ 方法原型 # */ func SM4Decrypt(data string, key ...string) (string, error) { SM4Key := overall.CONSTANT_CONFIG.Appsetup.AppKey if len(key) > 0 { SM4Key = strings.Join(key, "-") } SM4Key = processString(SM4Key, 16, "s") SM4Iv := "04TzMuvkHm_EZnHm" iv := []byte(SM4Iv) keySm4 := []byte(SM4Key) block, err := sm4.NewCipher(keySm4) if err != nil { return "", err } //使用hex解码 decodeString, err := hex.DecodeString(data) if err != nil { return "", err } //CBC模式 优点:具有较好的安全性,能够隐藏明文的模式和重复性。 缺点:加密过程是串行的,不适合并行处理。 blockMode := cipher.NewCBCDecrypter(block, iv) //下文有详解这段代码的含义 blockMode.CryptBlocks(decodeString, decodeString) //去掉明文后面的填充数据 plainText := unPaddingLastGroup(decodeString) return string(plainText), nil } // 判断字符串长度,多余的删除,不足的补充 func processString(s string, length int, pad string) string { // 如果字符串长度已经符合要求,直接返回 if len(s) == length { return s } // 如果字符串长度超过了要求,截取指定长度的部分 if len(s) > length { return s[:length] } // 如果字符串长度不足,使用pad字符串进行补充 return s + padString(pad, length-len(s)) } // 根据需要补充的字符和次数,生成补充字符串 func padString(pad string, times int) string { var result string for i := 0; i < times; i++ { result += pad } return result }