XinYeYouKu/app/third/dfpOpenSdk/util/symmetric.go

215 lines
5.9 KiB
Go
Raw Normal View History

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]
}