112 lines
2.4 KiB
Go
112 lines
2.4 KiB
Go
package cmb
|
|
|
|
import (
|
|
"crypto/cipher"
|
|
"crypto/rand"
|
|
"encoding/base64"
|
|
"fmt"
|
|
"github.com/tjfoc/gmsm/sm4"
|
|
)
|
|
|
|
func generateSm4Key() (string, error) {
|
|
keyBytes, err := generateKey()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return ByteArrayToHexString(keyBytes)
|
|
}
|
|
|
|
func generateKey() ([]byte, error) {
|
|
key := make([]byte, sm4.BlockSize)
|
|
_, err := rand.Read(key)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return key, nil
|
|
}
|
|
|
|
// ByteArrayToHexString 将字节数组转换为十六进制字符串
|
|
func ByteArrayToHexString(byteArray []byte) (string, error) {
|
|
if byteArray == nil {
|
|
return "", fmt.Errorf("byteArray is nil")
|
|
}
|
|
result := make([]byte, 0, len(byteArray)*2)
|
|
for _, b := range byteArray {
|
|
// 处理高 4 位
|
|
result = append(result, byteToHexChar(b>>4))
|
|
// 处理低 4 位
|
|
result = append(result, byteToHexChar(b&0x0F))
|
|
}
|
|
return string(result), nil
|
|
}
|
|
|
|
// byteToHexChar 将一个 4 位字节转换为对应的十六进制字符
|
|
func byteToHexChar(n byte) byte {
|
|
if n < 10 {
|
|
return '0' + n
|
|
}
|
|
return 'a' + n - 10
|
|
}
|
|
|
|
func SM4Encrypt(contentBytes []byte, encryptKey string) (string, error) {
|
|
d, err := base64.StdEncoding.DecodeString(encryptKey)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
cipherBlock, err := sm4.NewCipher(d)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
blockSize := cipherBlock.BlockSize()
|
|
iv := make([]byte, blockSize)
|
|
for i := 0; i < blockSize; i++ {
|
|
iv[i] = 0
|
|
}
|
|
|
|
blockMode := cipher.NewCBCEncrypter(cipherBlock, iv)
|
|
|
|
padding := blockSize - len(contentBytes)%blockSize
|
|
for i := 0; i < padding; i++ {
|
|
contentBytes = append(contentBytes, byte(padding))
|
|
}
|
|
cipherText := make([]byte, len(contentBytes))
|
|
blockMode.CryptBlocks(cipherText, contentBytes)
|
|
|
|
return base64.StdEncoding.EncodeToString(cipherText), nil
|
|
}
|
|
|
|
func SM4Decrypt(encrypted, encryptKey string) (string, error) {
|
|
d, err := base64.StdEncoding.DecodeString(encryptKey)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
cipherBlock, err := sm4.NewCipher(d)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
blockSize := cipherBlock.BlockSize()
|
|
iv := make([]byte, blockSize)
|
|
for i := 0; i < blockSize; i++ {
|
|
iv[i] = 0
|
|
}
|
|
|
|
cipherText, err := base64.StdEncoding.DecodeString(encrypted)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
plainText := make([]byte, len(cipherText))
|
|
blockMode := cipher.NewCBCDecrypter(cipherBlock, iv)
|
|
blockMode.CryptBlocks(plainText, cipherText)
|
|
|
|
plainTextLen := len(plainText)
|
|
padding := int(plainText[plainTextLen-1])
|
|
buff := plainText[:plainTextLen-padding]
|
|
|
|
return string(buff), nil
|
|
}
|