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

215 lines
5.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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