redisTemplate.Set(context.Background(), “privateKey”, privateKeyToString, g.OneDayDuration) return }
③测试用例
func TestSM2_Local_GenerateKeyPair(t *testing.T) { // 生成密钥对 publicKeyObj, privateKeyObj := generateLoc() // 输出公钥和私钥字符串 t.Log(“公钥字符串:”, PublicKeyToString(publicKeyObj)) // 040a5cccc33685eade33b0a1a40f1eea0f86ae93bd3cbb9f88fa466ca49a87bdbcd1ab65c9cb9f587a3b1f6d143f964acab78a23c2c37b1c16e2d16b796861f7bf t.Log(“私钥字符串:”, PrivateKeyToString(privateKeyObj)) // 5b8037839b43ee13804e4c9fb3626b8949f0f58729547f0da4e8415481243b03 } 打印结果: === RUN TestSM2_Local_GenerateKeyPair sm2_test.go:14: 公钥字符串:040a5cccc33685eade33b0a1a40f1eea0f86ae93bd3cbb9f88fa466ca49a87bdbcd1ab65c9cb9f587a3b1f6d143f964acab78a23c2c37b1c16e2d16b796861f7bf sm2_test.go:16: 私钥字符串:5b8037839b43ee13804e4c9fb3626b8949f0f58729547f0da4e8415481243b03 — PASS: TestSM2_Local_GenerateKeyPair (0.00s) PASS
2.使用公钥加密
①需求描述
要使用上面生成并缓存在redis
中的公钥字符串,对内容进行加密.
②编写代码
将公钥字符串反序列化转为公钥对象:
// StringToPublicKey 公钥字符串还原为 sm2.PublicKey 对象(与java中org.bouncycastle.crypto生成的公私钥完全互通使用) func StringToPublicKey(publicKeyStr string) (*sm2.PublicKey, error) { publicKeyBytes, err := hex.DecodeString(publicKeyStr) if err != nil { return nil, err } // 提取 x 和 y 坐标字节切片 curve := sm2.P256Sm2().Params() byteLen := (curve.BitSize + 7) / 8 xBytes := publicKeyBytes[1 : byteLen+1] yBytes := publicKeyBytes[byteLen+1 : 2*byteLen+1] // 将字节切片转换为大整数 x := new(big.Int).SetBytes(xBytes) y := new(big.Int).SetBytes(yBytes) // 创建 sm2.PublicKey 对象 publicKey := &sm2.PublicKey{ Curve: curve, X: x, Y: y, } return publicKey, nil } 使用公钥对象加密字符串: // publicKeyStr 公钥字符串, text 待加密明文字符串 func encryptLoc(publicKeyStr, text string) (string, error) { publicKey, err := StringToPublicKey(publicKeyStr) if err != nil { return “”, err } encryptStr, _ := sm2.Encrypt(publicKey, []byte(text), rand.Reader, sm2.C1C2C3) encodeToString := hex.EncodeToString(encryptStr) fmt.Println(“加密后的字符串:”, encodeToString) return strings.ToUpper(encodeToString), nil } 从redis取公钥并加密明文, 将上面两个函数整合: // SM2_Encrypt_Local sm2 本地加密 // // @version latest func SM2_Encrypt_Local(text string) (string, error) { // 先检测redis中是否缓存有密钥 redisTemplate := redis.RedisTemplate// 你自己的redis客户端获取方式 publicKeyStr, _ := redisTemplate.Get(context.Background(), “publicKey”).Result() publicKey := strings.ReplaceAll(publicKeyStr, “”", “”) if publicKey == “” { // 重新生成密钥 publicKey, _ = SM2_GenerateKeyPair_Local() } encrypt, err := encryptLoc(publicKey, text) if err != nil { return “”, err } return encrypt, nil }
③测试用例
将字符串 ABC123加密 func TestSM2_Local_Encrypt(t *testing.T) { publicKeyStr := “040a5cccc33685eade33b0a1a40f1eea0f86ae93bd3cbb9f88fa466ca49a87bdbcd1ab65c9cb9f587a3b1f6d143f964acab78a23c2c37b1c16e2d16b796861f7bf” publicKey, _ := StringToPublicKey(publicKeyStr) encryptStr, _ := sm2.Encrypt(publicKey, []byte(“ABC123”), rand.Reader, sm2.C1C2C3) encodeToString := hex.EncodeToString(encryptStr) t.Log(“加密后的字符串:”, encodeToString) } 打印结果: === RUN TestSM2_Local_Encrypt sm2_test.go:25: 加密后的字符串: 04d5bfb00dff8607a07337ff5999cbad8713a286c2655797148211dbf315b616faad48999428faf1597413d5d1cd81a425ccf192783c28cccd7a00ce618c759e29b82e5a34af99c34b0792d81026a6ca16317e76e11190c6564810a0737ceebb26a555498b23e0 — PASS: TestSM2_Local_Encrypt (0.00s) PASS
3.使用私钥解密
①需求描述
要使用上面生成并缓存在redis
中的私钥字符串,对加密的字符串进行解密
②编写代码
将私钥字符串反序列化转为私钥对象: // StringToPrivateKey 私钥还原为 sm2.PrivateKey对象(与java中org.bouncycastle.crypto生成的公私钥完全互通使用) func StringToPrivateKey(privateKeyStr string, publicKey *sm2.PublicKey) (*sm2.PrivateKey, error) { privateKeyBytes, err := hex.DecodeString(privateKeyStr) if err != nil { return nil, err } // 将字节切片转换为大整数 d := new(big.Int).SetBytes(privateKeyBytes) // 创建 sm2.PrivateKey 对象 privateKey := &sm2.PrivateKey{ PublicKey: *publicKey, D: d, } return privateKey, nil } 使用私钥对象解密密文字符串: func decryptLoc(publicKeyStr, privateKeyStr, cipherText string) (string, error) { publicKeyObj, err := StringToPublicKey(publicKeyStr) if err != nil { fmt.Println(err) } privateKeyObj, err := StringToPrivateKey(privateKeyStr, publicKeyObj) if err != nil { fmt.Println(err) } decodeString, err := hex.DecodeString(cipherText) decrypt, err := sm2.Decrypt(privateKeyObj, decodeString, sm2.C1C2C3) if err != nil { fmt.Println(err) } resultStr := string(decrypt) fmt.Println(“解密后的字符串:”, resultStr) return resultStr, nil } 从redis取私钥字符串并解密密文, 将上面两个函数整合: // SM2_Decrypt_Local sm2 本地解密 // // @version latest