2024-07-08 18:01:02 +08:00
|
|
|
|
package util
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"bytes"
|
|
|
|
|
"crypto/aes"
|
|
|
|
|
"crypto/cipher"
|
|
|
|
|
"crypto/rand"
|
|
|
|
|
"encoding/base64"
|
|
|
|
|
"github.com/tjfoc/gmsm/sm4"
|
|
|
|
|
"io"
|
|
|
|
|
"log"
|
|
|
|
|
"qteam/app/third/dfpOpenSdk/exception"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func AesEncrypt(content string, reqParamEncryptKey string) (string, error) {
|
|
|
|
|
key := []byte(reqParamEncryptKey)
|
|
|
|
|
block, err := aes.NewCipher(key)
|
|
|
|
|
if err != nil {
|
|
|
|
|
panic(err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//填充原文
|
|
|
|
|
blockSize := block.BlockSize()
|
|
|
|
|
content = string(PKCS5Padding([]byte(content), blockSize))
|
|
|
|
|
//初始向量IV必须是唯一,但不需要保密
|
|
|
|
|
cipherText := make([]byte, blockSize+len(content))
|
|
|
|
|
//block大小 16
|
|
|
|
|
iv := cipherText[:blockSize]
|
|
|
|
|
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
|
|
|
|
panic(err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//block大小和初始向量大小一定要一致
|
|
|
|
|
mode := cipher.NewCBCEncrypter(block, iv)
|
|
|
|
|
mode.CryptBlocks(cipherText[blockSize:], []byte(content))
|
|
|
|
|
|
|
|
|
|
return string(cipherText), nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func AesDecrypt(content string, reqParamEncryptKye string) (string, error) {
|
|
|
|
|
decodeKey, err := base64.StdEncoding.DecodeString(reqParamEncryptKye)
|
|
|
|
|
block, err := aes.NewCipher(decodeKey)
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ciphertext, err := base64.StdEncoding.DecodeString(content)
|
|
|
|
|
|
|
|
|
|
iv := ciphertext[:aes.BlockSize]
|
|
|
|
|
|
|
|
|
|
ciphertext = ciphertext[aes.BlockSize:]
|
|
|
|
|
mode := cipher.NewCBCDecrypter(block, iv)
|
|
|
|
|
|
|
|
|
|
mode.CryptBlocks(ciphertext, ciphertext)
|
|
|
|
|
|
|
|
|
|
result := base64.StdEncoding.EncodeToString(ciphertext)
|
|
|
|
|
return result, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func PKCS7UnPadding(origData []byte) []byte {
|
|
|
|
|
length := len(origData)
|
|
|
|
|
unpadding := int(origData[length-1])
|
|
|
|
|
return origData[:(length - unpadding)]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
|
|
|
|
|
padding := blockSize - len(ciphertext)%blockSize
|
|
|
|
|
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
|
|
|
|
|
return append(ciphertext, padtext...)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Sm4Encrypt sm4加密
|
|
|
|
|
// content 待加密内容
|
|
|
|
|
// reqParamEncryptKey 对称加密密钥 base64格式
|
|
|
|
|
func Sm4Encrypt(content string, reqParamEncryptKey string) (string, error) {
|
|
|
|
|
iv := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
|
|
|
|
err := sm4.SetIV(iv)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", exception.REQ_PARAM_ENCRYPT_ERR()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
decodeString, err := base64.StdEncoding.DecodeString(reqParamEncryptKey)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Println(err)
|
|
|
|
|
return "", exception.REQ_PARAM_ENCRYPT_ERR()
|
|
|
|
|
}
|
|
|
|
|
out, err := sm4.Sm4Cbc(decodeString, []byte(content), true)
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Println(err)
|
|
|
|
|
return "", exception.REQ_PARAM_ENCRYPT_ERR()
|
|
|
|
|
}
|
|
|
|
|
return base64.StdEncoding.EncodeToString(out), nil
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-10 10:44:07 +08:00
|
|
|
|
// SM4加密
|
|
|
|
|
func SM4Encrypt(data, reqParamEncryptKey string) (result string, err error) {
|
|
|
|
|
//字符串转byte切片
|
|
|
|
|
plainText := []byte(data)
|
|
|
|
|
//建议从配置文件中读取秘钥,进行统一管理
|
|
|
|
|
SM4Key, err := base64.StdEncoding.DecodeString(reqParamEncryptKey)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ivs := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
|
|
|
|
err = sm4.SetIV(ivs)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
iv := []byte(ivs)
|
|
|
|
|
key := []byte(SM4Key)
|
|
|
|
|
//实例化sm4加密对象
|
|
|
|
|
block, err := sm4.NewCipher(key)
|
|
|
|
|
if err != nil {
|
|
|
|
|
panic(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)
|
|
|
|
|
cipherString := base64.StdEncoding.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
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-08 18:01:02 +08:00
|
|
|
|
func Sm4Decrypt(content string, reqParamEncryptKey string) (string, error) {
|
|
|
|
|
iv := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
|
|
|
|
err := sm4.SetIV(iv)
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Println(err)
|
|
|
|
|
return "", exception.REQ_PARAM_ENCRYPT_ERR()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
decodeKey, err := base64.StdEncoding.DecodeString(reqParamEncryptKey)
|
|
|
|
|
decodeContent, _ := base64.StdEncoding.DecodeString(content)
|
|
|
|
|
out, err := sm4.Sm4Cbc(decodeKey, decodeContent, false)
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Println(err)
|
|
|
|
|
return "", exception.REQ_PARAM_ENCRYPT_ERR()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return string(out), nil
|
|
|
|
|
}
|
2024-07-10 10:44:07 +08:00
|
|
|
|
|
|
|
|
|
// SM4解密 传入string 输出string
|
|
|
|
|
func SM4Decrypt2(data, reqParamEncryptKey string) (res string, err error) {
|
|
|
|
|
//建议从配置文件中读取秘钥,进行统一管理
|
|
|
|
|
SM4Key, err := base64.StdEncoding.DecodeString(reqParamEncryptKey)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ivs := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
|
|
|
|
err = sm4.SetIV(ivs)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
iv := []byte(ivs)
|
|
|
|
|
key := []byte(SM4Key)
|
|
|
|
|
//实例化sm4加密对象
|
|
|
|
|
block, err := sm4.NewCipher(key)
|
|
|
|
|
if err != nil {
|
|
|
|
|
panic(err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
base64Content, err := base64.StdEncoding.DecodeString(data)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//CBC模式 优点:具有较好的安全性,能够隐藏明文的模式和重复性。 缺点:加密过程是串行的,不适合并行处理。
|
|
|
|
|
blockMode := cipher.NewCBCDecrypter(block, iv)
|
|
|
|
|
//下文有详解这段代码的含义
|
|
|
|
|
blockMode.CryptBlocks(base64Content, base64Content)
|
|
|
|
|
//去掉明文后面的填充数据
|
|
|
|
|
plainText := unPaddingLastGroup(base64Content)
|
|
|
|
|
//直接返回字符串类型,方便外部调用
|
|
|
|
|
return string(plainText), nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 去掉明文后面的填充数据
|
|
|
|
|
func unPaddingLastGroup(plainText []byte) []byte {
|
|
|
|
|
//1.拿到切片中的最后一个字节
|
|
|
|
|
length := len(plainText)
|
|
|
|
|
lastChar := plainText[length-1]
|
|
|
|
|
//2.将最后一个数据转换为整数
|
|
|
|
|
number := int(lastChar)
|
|
|
|
|
return plainText[:length-number]
|
|
|
|
|
}
|