package cmb import ( "crypto/rand" "encoding/base64" "encoding/hex" "fmt" "github.com/ZZMarquis/gm/sm4" "github.com/tjfoc/gmsm/sm2" "strings" sm22 "voucher/internal/pkg/cmb/sm2" "voucher/internal/pkg/cmb/sm2/model" "voucher/internal/pkg/cmb/sm2/sdk" ) // GenerateSm2Key 生成密钥对 func GenerateSm2Key() (string, string) { pri, _ := sm2.GenerateKey(rand.Reader) hexPri := pri.D.Text(16) // 获取公钥 publicKeyHex := publicKeyToString(&pri.PublicKey) return hexPri, publicKeyHex } // publicKeyToString 公钥sm2.PublicKey转字符串(与java中org.bouncycastle.crypto生成的公私钥完全互通使用) func publicKeyToString(publicKey *sm2.PublicKey) string { xBytes := publicKey.X.Bytes() yBytes := publicKey.Y.Bytes() // 确保坐标字节切片长度相同 byteLen := len(xBytes) if len(yBytes) > byteLen { byteLen = len(yBytes) } // 为坐标补齐前导零 xBytes = append(make([]byte, byteLen-len(xBytes)), xBytes...) yBytes = append(make([]byte, byteLen-len(yBytes)), yBytes...) // 添加 "04" 前缀 publicKeyBytes := append([]byte{0x04}, append(xBytes, yBytes...)...) return hex.EncodeToString(publicKeyBytes) } func Encrypt(sopPublicKey, input string) (string, error) { sm4Key := GenerateSM4Key() iv := GetSM4IV() encryptedBody, err := sm4.CBCEncrypt(sm4Key, iv, Padding([]byte(input), 1)) keyAndIv := AssemblingByteArray(sm4Key, iv) kvTmp, err := sm22.NewSm2(). SetHexPublicKey(sopPublicKey). SetData([]byte(base64.StdEncoding.EncodeToString(keyAndIv))). SetSdk(sdk.NewCmbLifeSdk()). SetCipherType(model.C1C3C2). Encrypt(). ToString() if err != nil { return "", err } return fmt.Sprintf("%s|%s", base64.StdEncoding.EncodeToString([]byte(kvTmp)), base64.StdEncoding.EncodeToString(encryptedBody)), nil } func Decrypt(privateKey, input string) (string, error) { tmpDataArr := strings.Split(input, "|") if len(tmpDataArr) != 2 { return "", fmt.Errorf("数据格式错误") } keyAndIvStr := tmpDataArr[0] encryptedBody := tmpDataArr[1] kvBase64Tmp, err := sm22.NewSm2(). SetHexPrivateKey(privateKey). SetBase64StringData(keyAndIvStr). SetSdk(sdk.NewCmbLifeSdk()). SetCipherType(model.C1C3C2). Decrypt(). ToString() if err != nil { return "", err } kvTmp, err := base64.StdEncoding.DecodeString(kvBase64Tmp) if err != nil { return "", err } kvArr := strings.Split(string(kvTmp), "|") if len(tmpDataArr) != 2 { return "", fmt.Errorf("数据格式错误!") } plainKey := []byte(kvArr[0]) plainIv := []byte(kvArr[1]) data2, err := base64.StdEncoding.DecodeString(encryptedBody) if err != nil { return "", err } plainText, err := sm4.CBCDecrypt(plainKey, plainIv, data2) if err != nil { return "", err } return string(Padding(plainText, 0)), nil } func Sign(privateKey, input string) (string, error) { signData, err := sm22.NewSm2(). SetHexPrivateKey(privateKey). SetData([]byte(input)). Sign(). ToString() if err != nil { return "", err } return base64.StdEncoding.EncodeToString([]byte(signData)), nil } func Verify(publicKey, input, sign string) (bool, error) { ok, err := sm22.NewSm2(). SetHexPublicKey(publicKey). SetData([]byte(input)). SetBase64Signature(sign). Verify(). ToBool() if err != nil { return false, err } if !ok { return false, nil } return true, nil }