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 }