gmsm
gmsm copied to clipboard
JAVA对GO生成的签名,验证失败.
fork代码修改后,可以正常做 SM2WITHSM3了,但是对方是JAVA服务端,验证签名失败. 正常的PKCS1祼签JAVA方也不能验证. 查看了一下ASN1的数据 GO生成的签名,R,S长度32,JAVA长度33
GO可以验证JAVA和GO自己的签名 JAVA不能验证GO生成的签名
GO
ASN.1 Sequence (70字节)
ASN.1 Integer (32字节)
49953602798973186633919026302796227754575575121265967941549104619692819388197
ASN.1 Integer (32字节)
6323159028519601678585446620409841784998903456586007702140898792008835206132
JAVA
ASN.1 Sequence (72字节)
ASN.1 Integer (33字节)
70468025293370294943352223829577765421262310906429137293791810763219733692696
ASN.1 Integer (33字节)
98640631558403820175130960459496903133090903563226543449918394768633700812864
请问是否有解决方案了?我看java和go在生成密钥时候就不一样,java的公钥是获取的Q,但是golang是获取的X、Y,还请有大佬解答下
@aomirun 请教下 SM2WITHSM3是怎么实现的啊
@sax1412 因国密PKCS7各服务端验证有所区别,根据对方pkcs7签名的ASN1结构,来修改PKCS7生成的参数.
@jiuerzhange 目前还没有,主要是国密签名机好像对C 系的uin8没有做支持,使得最终签名验证失败.
感觉某些地方不严谨, 没有与其它语言C、java做关联性验证。 导致自己加密解密,不能与其它语言兼容使用。 算法是正确的,就是细节问题。
sm2的加解密我拿java互通了,可签名验签没搞了,有大佬整一下吗
sm2的加解密我拿java互通了,可签名验签没搞了,有大佬整一下吗
求一下,java与go互通这块的资料。我java是用hutool生成的,在go这里一直通不了。
golang
大佬,有go的demo吗?我这边跟java的老是互通不了
解决了吗?我这也不通
解决了吗?我这也不通
我只是加解密可以了,签名没试过,你可以参考一下。https://blog.csdn.net/4color/article/details/127305555
解决了吗?我这也不通
我解决了、具体参考我写的博客https://blog.csdn.net/hahawangzi520/article/details/126187783
sm2的加解密我拿java互通了,可签名验签没搞了,有大佬整一下吗
我解决了、具体参考我写的博客https://blog.csdn.net/hahawangzi520/article/details/126187783
对接过招行,所以看了一下招行的java使用demo,使用的是hutool的加密库,签名曲线用的sm2p256v1,对SM2Signer生成的签名进行了自定义解析 我自己使用本库gm2的默认签名和验签进行了简单修改,以下仅包含签名的简单示例代码
// gmsm库的sm2签名
r, s, err := Sm2Sign(priv, msg, nil, random)
if err != nil {
return nil, err
}
return asn1.Marshal(sm2Signature{r, s})
最终返回的是asn1的结构体序列化,可以将r,s的[]byte添加到bytes.Buffer,[]byte长度为32不足前面补0
// 修改后的签名
rByte := r.Bytes()
sByte := s.Bytes()
if len(rByte) < 32 {
rByte = append([]byte{0}, rByte...)
}
if len(sByte) < 32 {
sByte = append([]byte{0}, sByte...)
}
var buffer bytes.Buffer
buffer.Write(rByte)
buffer.Write(sByte)
java的demo中的签名
ECParameterSpec spec = ECNamedCurveTable.getParameterSpec("sm2p256v1");
ECDomainParameters domainParameters = new ECDomainParameters(spec.getCurve(), spec.getG(), spec.getN(),spec.getH(),spec.getSeed());
ECPrivateKeyParameters privateKey = new ECPrivateKeyParameters(new BigInteger(1, key), domainParameters);
ParametersWithID parameters = new ParametersWithID(privateKey, "1234567812345678".getBytes());
byte[] data = msg.getBytes();
SM2Signer signer = new SM2Signer();
signer.init(true, parameters);
signer.update(data, 0, data.length);
public byte[] signature=signer.generateSignature();
ASN1InputStream stream = new ASN1InputStream(new ByteArrayInputStream(signature));
try {
ASN1Sequence primitive = (ASN1Sequence)stream.readObject();
Enumeration enumeration = primitive.getObjects();
BigInteger R = ((ASN1Integer)enumeration.nextElement()).getValue();
BigInteger S = ((ASN1Integer)enumeration.nextElement()).getValue();
byte[] bytes = new byte[64];
byte[] r = format(R.toByteArray());
byte[] s = format(S.toByteArray());
System.arraycopy(r, 0, bytes, 0, 32);
System.arraycopy(s, 0, bytes, 32, 32);
return bytes;
} catch (Exception e) {
throw new Exception();
}
对接过招行,所以看了一下招行的java使用demo,使用的是hutool的加密库,签名曲线用的sm2p256v1,对SM2Signer生成的签名进行了自定义解析 我自己使用本库gm2的默认签名和验签进行了简单修改,以下仅包含签名的简单示例代码
// gmsm库的sm2签名 r, s, err := Sm2Sign(priv, msg, nil, random) if err != nil { return nil, err } return asn1.Marshal(sm2Signature{r, s})
最终返回的是asn1的结构体序列化,可以将r,s的[]byte添加到bytes.Buffer,[]byte长度为32不足前面补0
// 修改后的签名 rByte := r.Bytes() sByte := s.Bytes() if len(rByte) < 32 { rByte = append([]byte{0}, rByte...) } if len(sByte) < 32 { sByte = append([]byte{0}, sByte...) } var buffer bytes.Buffer buffer.Write(rByte) buffer.Write(sByte)
java的demo中的签名
ECParameterSpec spec = ECNamedCurveTable.getParameterSpec("sm2p256v1"); ECDomainParameters domainParameters = new ECDomainParameters(spec.getCurve(), spec.getG(), spec.getN(),spec.getH(),spec.getSeed()); ECPrivateKeyParameters privateKey = new ECPrivateKeyParameters(new BigInteger(1, key), domainParameters); ParametersWithID parameters = new ParametersWithID(privateKey, "1234567812345678".getBytes()); byte[] data = msg.getBytes(); SM2Signer signer = new SM2Signer(); signer.init(true, parameters); signer.update(data, 0, data.length); public byte[] signature=signer.generateSignature(); ASN1InputStream stream = new ASN1InputStream(new ByteArrayInputStream(signature)); try { ASN1Sequence primitive = (ASN1Sequence)stream.readObject(); Enumeration enumeration = primitive.getObjects(); BigInteger R = ((ASN1Integer)enumeration.nextElement()).getValue(); BigInteger S = ((ASN1Integer)enumeration.nextElement()).getValue(); byte[] bytes = new byte[64]; byte[] r = format(R.toByteArray()); byte[] s = format(S.toByteArray()); System.arraycopy(r, 0, bytes, 0, 32); System.arraycopy(s, 0, bytes, 32, 32); return bytes; } catch (Exception e) { throw new Exception(); }
这是解决了吗,我看了 一下很多都是验签的问题,我现在也卡在这里
对接过招行,所以看了一下招行的java使用demo,使用的是hutool的加密库,签名曲线用的sm2p256v1,对SM2Signer生成的签名进行了自定义解析 我自己使用本库gm2的默认签名和验签进行了简单修改,以下仅包含签名的简单示例代码
// gmsm库的sm2签名 r, s, err := Sm2Sign(priv, msg, nil, random) if err != nil { return nil, err } return asn1.Marshal(sm2Signature{r, s})
最终返回的是asn1的结构体序列化,可以将r,s的[]byte添加到bytes.Buffer,[]byte长度为32不足前面补0
// 修改后的签名 rByte := r.Bytes() sByte := s.Bytes() if len(rByte) < 32 { rByte = append([]byte{0}, rByte...) } if len(sByte) < 32 { sByte = append([]byte{0}, sByte...) } var buffer bytes.Buffer buffer.Write(rByte) buffer.Write(sByte)
java的demo中的签名
ECParameterSpec spec = ECNamedCurveTable.getParameterSpec("sm2p256v1"); ECDomainParameters domainParameters = new ECDomainParameters(spec.getCurve(), spec.getG(), spec.getN(),spec.getH(),spec.getSeed()); ECPrivateKeyParameters privateKey = new ECPrivateKeyParameters(new BigInteger(1, key), domainParameters); ParametersWithID parameters = new ParametersWithID(privateKey, "1234567812345678".getBytes()); byte[] data = msg.getBytes(); SM2Signer signer = new SM2Signer(); signer.init(true, parameters); signer.update(data, 0, data.length); public byte[] signature=signer.generateSignature(); ASN1InputStream stream = new ASN1InputStream(new ByteArrayInputStream(signature)); try { ASN1Sequence primitive = (ASN1Sequence)stream.readObject(); Enumeration enumeration = primitive.getObjects(); BigInteger R = ((ASN1Integer)enumeration.nextElement()).getValue(); BigInteger S = ((ASN1Integer)enumeration.nextElement()).getValue(); byte[] bytes = new byte[64]; byte[] r = format(R.toByteArray()); byte[] s = format(S.toByteArray()); System.arraycopy(r, 0, bytes, 0, 32); System.arraycopy(s, 0, bytes, 32, 32); return bytes; } catch (Exception e) { throw new Exception(); }
这是解决了吗,我看了 一下很多都是验签的问题,我现在也卡在这里
我这边是验签通过了的,Java端验签,具体得看Java端对签名值的解析方式,像我这边对接的他是要求128位长度的hex,但是本库的签名返回对象是ASN1的结构体,得到的一般是144位,偶尔长度不够,所以需要补0,单从长度上就不一致,看hutool工具类的验签实现,他是利用解析的两个大数,R和S来做的验证,所以他转成[]byte后直接截取[]byte的前32位 和后32位分别做R和S就通过了,所以我这边做了一下转换,两边统一了序列化对象应该没什么问题
我解决了java和go之间的国密算法签名问题、具体参考我写的博客、花了很多精力攻克的、虽然是付费的、也希望大佬能支持下原创。
https://blog.csdn.net/hahawangzi520/article/details/126187783
@ahKevinXy 我解决了java和go之间的国密算法签名问题、具体参考我写的博客、花了很多精力攻克的、虽然是付费的、也希望大佬能支持下原创。
https://blog.csdn.net/hahawangzi520/article/details/126187783
@ahKevinXy 我解决了java和go之间的国密算法签名问题、具体参考我写的博客、花了很多精力攻克的、虽然是付费的、也希望大佬能支持下原创。
https://blog.csdn.net/hahawangzi520/article/details/126187783
没事 我写了一个 Java 的sdk 解决了,付费就没有必要看了
成
这边 可以提供一下源码吗,最近我也是对接招商银行,就是验签不通
成
这边 可以提供一下源码吗,最近我也是对接招商银行,就是验签不通
上面的示例代码就可以,修改后的签名就是(验签同理),健壮性你自己保证
我用 Java 写了一个单独的验签了
我解决了java和go之间的国密算法签名问题、具体参考我写的博客、花了很多精力攻克的、虽然是付费的、也希望大佬能支持下原创。
https://blog.csdn.net/hahawangzi520/article/details/126187783
我就去看了,然而什么内容都没讲到,引用他的原文“(4)golang golang的sm2解密有时候成功,有时候失败,经过我反复测试,是testing依赖模块导致的,但是底层原因未知,我把代码放到run.go的main方法里,都是正常执行。如果有小伙伴懂的话,可以私信我。” 下面例子也是普通的例子,这就叫解决了?!
我解决了java和go之间的国密算法签名问题、具体参考我写的博客、花了很多精力攻克的、虽然是付费的、也希望大佬能支持下原创。 https://blog.csdn.net/hahawangzi520/article/details/126187783
我就去看了,然而什么内容都没讲到,引用他的原文“(4)golang golang的sm2解密有时候成功,有时候失败,经过我反复测试,是testing依赖模块导致的,但是底层原因未知,我把代码放到run.go的main方法里,都是正常执行。如果有小伙伴懂的话,可以私信我。” 下面例子也是普通的例子,这就叫解决了?!
源码发一下
@ahKevinXy 用 Golang 写了一个完整的示例 https://github.com/hxkjason/cmb_SM3withSM2_sign_demo, FYI。
@ahKevinXy 用 Golang 写了一个完整的示例 https://github.com/hxkjason/cmb_SM3withSM2_sign_demo, FYI。
试一下看看,我的java的一直不稳定
@ahKevinXy 用 Golang 写了一个完整的示例 https://github.com/hxkjason/cmb_SM3withSM2_sign_demo, FYI。
感谢啊,折腾了快一天,从你这搞定了
@yidashi 不谢~ 很高兴能够给你带来一点帮助~
@ahKevinXy 用 Golang 写了一个完整的示例 https://github.com/hxkjason/cmb_SM3withSM2_sign_demo, FYI。
感谢啊,折腾了快一天,从你这搞定了
你怎么成功的,为啥我的不行
package sm2
import (
"bytes"
"crypto/rand"
"encoding/hex"
"math/big"
"strings"
"github.com/tjfoc/gmsm/sm2"
)
func Sign(signContent, privateKey, userId string) string {
signContent = strings.ReplaceAll(signContent, `"`, `\"`)
priKey := TransHexToSm2PrivateKey(privateKey)
r, s, err := sm2.Sm2Sign(priKey, []byte(signContent), []byte(userId), rand.Reader)
if err != nil {
return ""
}
rBytes, sBytes := r.Bytes(), s.Bytes()
rLen, sLen := len(rBytes), len(sBytes)
regularSize := 32
if rLen < regularSize {
for i := 0; i < regularSize-rLen; i++ {
rBytes = append(rBytes, 0)
}
}
if sLen < regularSize {
for i := 0; i < regularSize-sLen; i++ {
sBytes = append(sBytes, 0)
}
}
var buffer bytes.Buffer
buffer.Write(rBytes)
buffer.Write(sBytes)
return strings.ToUpper(hex.EncodeToString(buffer.Bytes()))
}
// TransHexToSm2PrivateKey 将16进制私钥转换成sm2私钥实例
func TransHexToSm2PrivateKey(HexPrivateKey string) *sm2.PrivateKey {
d := new(big.Int)
d.SetString(HexPrivateKey, 16)
privateKey := new(sm2.PrivateKey)
privateKey.D = d
curve := sm2.P256Sm2()
privateKey.PublicKey.Curve = curve
privateKey.PublicKey.X, privateKey.PublicKey.Y = curve.ScalarBaseMult(d.Bytes())
return privateKey
}
@ahKevinXy 用 Golang 写了一个完整的示例 https://github.com/hxkjason/cmb_SM3withSM2_sign_demo, FYI。
感谢啊,折腾了快一天,从你这搞定了
你怎么成功的,为啥我的不行
package sm2 import ( "bytes" "crypto/rand" "encoding/hex" "math/big" "strings" "github.com/tjfoc/gmsm/sm2" ) func Sign(signContent, privateKey, userId string) string { signContent = strings.ReplaceAll(signContent, `"`, `\"`) priKey := TransHexToSm2PrivateKey(privateKey) r, s, err := sm2.Sm2Sign(priKey, []byte(signContent), []byte(userId), rand.Reader) if err != nil { return "" } rBytes, sBytes := r.Bytes(), s.Bytes() rLen, sLen := len(rBytes), len(sBytes) regularSize := 32 if rLen < regularSize { for i := 0; i < regularSize-rLen; i++ { rBytes = append(rBytes, 0) } } if sLen < regularSize { for i := 0; i < regularSize-sLen; i++ { sBytes = append(sBytes, 0) } } var buffer bytes.Buffer buffer.Write(rBytes) buffer.Write(sBytes) return strings.ToUpper(hex.EncodeToString(buffer.Bytes())) } // TransHexToSm2PrivateKey 将16进制私钥转换成sm2私钥实例 func TransHexToSm2PrivateKey(HexPrivateKey string) *sm2.PrivateKey { d := new(big.Int) d.SetString(HexPrivateKey, 16) privateKey := new(sm2.PrivateKey) privateKey.D = d curve := sm2.P256Sm2() privateKey.PublicKey.Curve = curve privateKey.PublicKey.X, privateKey.PublicKey.Y = curve.ScalarBaseMult(d.Bytes()) return privateKey }
这个确实可以通过招行java的验签,有个大坑,如果是非saas模式,不能加那个平台签 “paltsigdat”, 否则一直会提示 “签名信息无效” 大坑 最无语的是用官方提供的java demo ,同一套key, 加上平台签名是可以通过的,golang版本死活通过不了,去掉又可以