栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Go语言

java签名验签

Go语言 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

java签名验签

近期go项目对接第三方Java服务,第三方要求使用国密sm3/sm2算法进行数据签名验签,特记录go端开发注意事项

1 关于密钥对

密钥生成可以使用openssl库,openssl版本至少是1.1.1,终端运行 openssl version

检查版本,之前版本不支持sm2/sm3, openssl官网 https://www.openssl.org/source/

检查椭圆曲线是否包含sm2,如下所示是支持sm2的。

$ openssl ecparam -list_curves | grep SM2

SM2 : SM2 curve over a 256 bit prime field

密钥生成流程,存在第四步的原因是go使用的库需要读取pkcs#8格式私钥pem文件:

1 生成sm2私钥: openssl ecparam -genkey -name SM2 -out sm2PriKey.pem

2 sm2私钥导出公钥: openssl ec -in sm2PriKey.pem -pubout -out sm2PubKey.pem

3 查看私钥: openssl ec -in sm2PriKey.pem -text

4 私钥pkcs#1转pkcs#8: openssl pkcs8 -topk8 -inform PEM -in sm2PriKey.pem -outform pem -nocrypt -out sm2PriKeyPkcs8.pem

2 go签名验签代码

1 读取公钥pem文件, 将公钥X/Y的bytes拼接base64编码,函数示例:

func DealPubKey() {

// 公钥X/Y的bytes拼接后base64编码

PubKeyPath := "/home/xx/sm2PubKey.pem"

pubKey, e := sm2.ReadPublicKeyFromPem(PubKeyPath, nil)

if e != nil {

log.Println("pubKeyPem read failed, error: ", e)

}

var buf bytes.Buffer

buf.Write(pubKey.X.Bytes())

buf.Write(pubKey.Y.Bytes())

XY := base64.StdEncoding.EncodeToString(buf.Bytes())

log.Println("pubKey XY base64--->", XY)

}

2 sm2签名验签使用的包”github.com/tjfoc/gmsm/sm2″, go mod自动安装不会安装最新版本, go.mod不要添加此包,

github最新版本是是V1.2, 切换到项目目录, 终端运行 go get github.com/tjfoc/gmsm@master

安装最新版本后会自动添加到go.mod

3 “github.com/tjfoc/gmsm/sm2″使用签名函数为 sm2.Sm2Sign, 此函数会将输入的[]bytes类型数据sm3摘要运算后进行sm2签名, 对应验签函数sm2.Sm2Verify

4 函数sm2.Sign默认是使用sha-512进行摘要运算,与服务端Java签名验签失败.

代码示例:

package main

import (

"bytes"

"encoding/base64"

"fmt"

"github.com/tjfoc/gmsm/sm2"

"github.com/tjfoc/gmsm/sm3"

"log"

"math/big"

"os"

)

var (

default_uid = []byte{0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38}

)

func Sign(body string) (string, error) {

cwd, _ := os.Getwd()

PriKeyPath := cwd + string(os.PathSeparator) + "sm2PriKeyPkcs8.pem"

priKey, e := sm2.ReadPrivateKeyFromPem(PriKeyPath, nil)

if e != nil {

log.Println("priKeyPem read failed, error: ", e)

return "", e

}

r, s, err := sm2.Sm2Sign(priKey, []byte(body), default_uid)

if err != nil {

log.Println("priKey sign error: ", err)

return "", err

}

//Buffer是一个实现了读写方法的可变大小的字节缓冲

var buffer bytes.Buffer

buffer.Write(r.Bytes())

buffer.Write(s.Bytes())

signature := base64.StdEncoding.EncodeToString(buffer.Bytes())

log.Println("priKey signature base64: ", signature)

return signature, nil

}

func Verify(body, signature string) {

cwd, _ := os.Getwd()

PubKeyPath := cwd + string(os.PathSeparator) + "sm2PubKey.pem"

pubKey, e := sm2.ReadPublicKeyFromPem(PubKeyPath, nil)

if e != nil {

log.Println("pubKeyPem read failed, error: ", e)

}

d64, err := base64.StdEncoding.DecodeString(signature)

if err != nil {

log.Println("base64 decode error: ", err)

}

l := len(d64)

br := d64[:l/2]

bs := d64[l/2:]

var ri, si big.Int

r := ri.SetBytes(br)

s := si.SetBytes(bs)

v := sm2.Sm2Verify(pubKey, []byte(body), default_uid, r, s)

log.Printf("pubKey verified: %vn", v)

}

func main() {

body := `{"name":"mike","gender":"male"}`

signature, _ := Sign(body)

Verify(body, signature)

}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/944421.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号