当前位置:   article > 正文

golang使用SM2(SM2withSM3)签名、验签数据

sm2withsm3

场景

对接招行支付

标准

密钥

私钥:Hex格式,SM2标准秘钥格式,私钥为32字节字节流,转换为HEX格式为64字节
公钥:base64格式,并且符合ANS1标准,base64编码后总长度为124字节
SM2标准公钥头:3059301306072A8648CE3D020106082A811CCF5501822D03420004

签名算法

数字签名采用SM2withSM3签名算法,签名方式为PKCS#1裸签名,签名USER_ID使用国密局推荐ID,即“1234567812345678”,使用国密私钥对签名字符串进行加签,生成签名值。

Start

依赖

import (
	"crypto/rand"
	"encoding/base64"
	"encoding/hex"
	"fmt"
	"github.com/ZZMarquis/gm/sm2"
	"strings"
)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

公钥转base64

func PubToBase64(pub *sm2.PublicKey) string {
	pub.GetRawBytes()
	bytes := pub.X.Bytes()
	bytes = append(bytes, pub.Y.Bytes()...)
	pubHex := "3059301306072a8648ce3d020106082a811ccf5501822d03420004" + hex.EncodeToString(bytes)
	decode, _ := hex.DecodeString(pubHex)
	base64Pub := base64.StdEncoding.EncodeToString(decode)
	return base64Pub
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

私钥转hex

func PriToHex(pri *sm2.PrivateKey) string {
	hex := hex.EncodeToString(pri.GetRawBytes())
	return hex
}
  • 1
  • 2
  • 3
  • 4

私钥生成公钥

func PriToBase64Pub(pri *sm2.PrivateKey) string {
	pub := sm2.CalculatePubKey(pri)
	base64Pub := PubToBase64(pub)
	return base64Pub
}
  • 1
  • 2
  • 3
  • 4
  • 5

生成密钥对

func Generate() (string, string) {
	pri, pub, _ := sm2.GenerateKey(rand.Reader)
	return PriToHex(pri), PubToBase64(pub)
}
  • 1
  • 2
  • 3
  • 4

Hex私钥转私钥对象

func HexToPri(priStr string) *sm2.PrivateKey {
	// 解码hex私钥
	privateKeyByte, _ := hex.DecodeString(priStr)
	// 转成go版的私钥
	pri, err := sm2.RawBytesToPrivateKey(privateKeyByte)
	if err != nil {
		panic("私钥加载异常")
	}
	return pri
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

base64公钥转公钥对象

func Base64ToPub(pubStr string) *sm2.PublicKey {
	decode, _ := base64.StdEncoding.DecodeString(pubStr)
	pubHex := hex.EncodeToString(decode)
	pubHex = strings.ReplaceAll(pubHex, "3059301306072a8648ce3d020106082a811ccf5501822d03420004", "")
	pubByte, _ := hex.DecodeString(pubHex)
	pub, _ := sm2.RawBytesToPublicKey(pubByte)
	return pub
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

签名

func Sign(data string, pri *sm2.PrivateKey) string {
	signature, err := sm2.Sign(pri, []byte("1234567812345678"), []byte(data))
	if err != nil {
		panic("云闪付签名错误")
	}
	// 转 base64
	sign := base64.StdEncoding.EncodeToString(signature)
	return sign
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

验签

func Verify(data, sign string, pub *sm2.PublicKey) bool {
	sign1, _ := base64.StdEncoding.DecodeString(sign)
	return sm2.Verify(pub, []byte("1234567812345678"), []byte(data), sign1)
}
  • 1
  • 2
  • 3
  • 4

测试

func Test() {
	//生成密钥对
	hexPri, basePub := Generate()
	println("******* 生成 hex私钥:" + hexPri)
	println("******* 生成 base公钥:" + basePub)
	//Hex私钥转私钥对象
	pri := HexToPri(hexPri)
	//base64公钥转公钥对象
	pub := Base64ToPub(basePub)
	//私钥生成公钥
	base64Pub := PriToBase64Pub(pri)
	println("******* 私钥生成base64公钥:" + base64Pub)
	//私钥转hex
	priHex := PriToHex(pri)
	println("******* 私钥转hex:" + priHex)
	//公钥转base64
	pubBase := PubToBase64(pub)
	println("******* 公钥转base64:" + pubBase)
	//签名
	sign := Sign("abc=123", pri)
	println("******* 签名:" + sign)
	//验签
	ver := Verify("abc=123", sign, pub)
	println(fmt.Sprintf("******* 验签:%t", ver))
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
******* 生成 hex私钥:ad606a552feb3b46b2ad47eab8491da7a97d796385b01149aac1e3e5c53f876a
******* 生成 base公钥:MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEJhdEFCw7pKnAR9mPZYKCkntiz+A1HRX5rDP1a2lYQjxXY2zLm4PoYm9hdlayBkGx/kzr/EIeapsxJa5Y+fAxMg==
******* 私钥生成base64公钥:MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEJhdEFCw7pKnAR9mPZYKCkntiz+A1HRX5rDP1a2lYQjxXY2zLm4PoYm9hdlayBkGx/kzr/EIeapsxJa5Y+fAxMg==
******* 私钥转hex:ad606a552feb3b46b2ad47eab8491da7a97d796385b01149aac1e3e5c53f876a
******* 公钥转base64:MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEJhdEFCw7pKnAR9mPZYKCkntiz+A1HRX5rDP1a2lYQjxXY2zLm4PoYm9hdlayBkGx/kzr/EIeapsxJa5Y+fAxMg==
******* 签名:MEQCIEn0F0EUVWGNvH7bMiveXNHFzOCVZkT+X4Y9zI9AL/HLAiAMScSwJs/8ZEf2QLw4ThYYqWvgAG+A0Lj3bq+ljvww6Q==
******* 验签:true

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/煮酒与君饮/article/detail/998443
推荐阅读
相关标签
  

闽ICP备14008679号