tjfoc / gmsm

GM SM2/3/4 library based on Golang (基于Go语言的国密SM2/SM3/SM4算法库)
http://www.wutongchain.com
Apache License 2.0
1.74k stars 583 forks source link

JAVA对GO生成的签名,验证失败. #165

Open aomirun opened 2 years ago

aomirun commented 2 years ago

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
jiuerzhange commented 2 years ago

请问是否有解决方案了?我看java和go在生成密钥时候就不一样,java的公钥是获取的Q,但是golang是获取的X、Y,还请有大佬解答下

sax1412 commented 2 years ago

@aomirun 请教下 SM2WITHSM3是怎么实现的啊

aomirun commented 2 years ago

@sax1412 因国密PKCS7各服务端验证有所区别,根据对方pkcs7签名的ASN1结构,来修改PKCS7生成的参数.

aomirun commented 2 years ago

@jiuerzhange 目前还没有,主要是国密签名机好像对C 系的uin8没有做支持,使得最终签名验证失败.

lala0257 commented 1 year ago

感觉某些地方不严谨, 没有与其它语言C、java做关联性验证。 导致自己加密解密,不能与其它语言兼容使用。 算法是正确的,就是细节问题。

liuhaichaogithub commented 1 year ago

sm2的加解密我拿java互通了,可签名验签没搞了,有大佬整一下吗

4color commented 1 year ago

sm2的加解密我拿java互通了,可签名验签没搞了,有大佬整一下吗

求一下,java与go互通这块的资料。我java是用hutool生成的,在go这里一直通不了。

jqtong commented 1 year ago

golang

大佬,有go的demo吗?我这边跟java的老是互通不了

jqtong commented 1 year ago

解决了吗?我这也不通

4color commented 1 year ago

解决了吗?我这也不通

我只是加解密可以了,签名没试过,你可以参考一下。https://blog.csdn.net/4color/article/details/127305555

jiuerzhange commented 1 year ago

解决了吗?我这也不通

我解决了、具体参考我写的博客https://blog.csdn.net/hahawangzi520/article/details/126187783

jiuerzhange commented 1 year ago

sm2的加解密我拿java互通了,可签名验签没搞了,有大佬整一下吗

我解决了、具体参考我写的博客https://blog.csdn.net/hahawangzi520/article/details/126187783

lish96 commented 1 year ago

对接过招行,所以看了一下招行的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();
        }
ahKevinXy commented 1 year ago

对接过招行,所以看了一下招行的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();
        }

这是解决了吗,我看了 一下很多都是验签的问题,我现在也卡在这里

lish96 commented 1 year ago

对接过招行,所以看了一下招行的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就通过了,所以我这边做了一下转换,两边统一了序列化对象应该没什么问题

jiuerzhange commented 1 year ago

我解决了java和go之间的国密算法签名问题、具体参考我写的博客、花了很多精力攻克的、虽然是付费的、也希望大佬能支持下原创。

https://blog.csdn.net/hahawangzi520/article/details/126187783

jiuerzhange commented 1 year ago

@ahKevinXy 我解决了java和go之间的国密算法签名问题、具体参考我写的博客、花了很多精力攻克的、虽然是付费的、也希望大佬能支持下原创。

https://blog.csdn.net/hahawangzi520/article/details/126187783

ahKevinXy commented 1 year ago

@ahKevinXy 我解决了java和go之间的国密算法签名问题、具体参考我写的博客、花了很多精力攻克的、虽然是付费的、也希望大佬能支持下原创。

https://blog.csdn.net/hahawangzi520/article/details/126187783

没事 我写了一个 Java 的sdk 解决了,付费就没有必要看了

ahKevinXy commented 1 year ago

这边 可以提供一下源码吗,最近我也是对接招商银行,就是验签不通

lish96 commented 1 year ago

这边 可以提供一下源码吗,最近我也是对接招商银行,就是验签不通

上面的示例代码就可以,修改后的签名就是(验签同理),健壮性你自己保证

ahKevinXy commented 1 year ago

我用 Java 写了一个单独的验签了

jinigithub commented 1 year ago

我解决了java和go之间的国密算法签名问题、具体参考我写的博客、花了很多精力攻克的、虽然是付费的、也希望大佬能支持下原创。

https://blog.csdn.net/hahawangzi520/article/details/126187783

我就去看了,然而什么内容都没讲到,引用他的原文“(4)golang golang的sm2解密有时候成功,有时候失败,经过我反复测试,是testing依赖模块导致的,但是底层原因未知,我把代码放到run.go的main方法里,都是正常执行。如果有小伙伴懂的话,可以私信我。” 下面例子也是普通的例子,这就叫解决了?!

ahKevinXy commented 1 year ago

我解决了java和go之间的国密算法签名问题、具体参考我写的博客、花了很多精力攻克的、虽然是付费的、也希望大佬能支持下原创。 https://blog.csdn.net/hahawangzi520/article/details/126187783

我就去看了,然而什么内容都没讲到,引用他的原文“(4)golang golang的sm2解密有时候成功,有时候失败,经过我反复测试,是testing依赖模块导致的,但是底层原因未知,我把代码放到run.go的main方法里,都是正常执行。如果有小伙伴懂的话,可以私信我。” 下面例子也是普通的例子,这就叫解决了?!

源码发一下

hxkjason commented 1 year ago

@ahKevinXy 用 Golang 写了一个完整的示例 https://github.com/hxkjason/cmb_SM3withSM2_sign_demo, FYI。

ahKevinXy commented 1 year ago

@ahKevinXy 用 Golang 写了一个完整的示例 https://github.com/hxkjason/cmb_SM3withSM2_sign_demo, FYI。

试一下看看,我的java的一直不稳定

yidashi commented 1 year ago

@ahKevinXy 用 Golang 写了一个完整的示例 https://github.com/hxkjason/cmb_SM3withSM2_sign_demo, FYI。

感谢啊,折腾了快一天,从你这搞定了

hxkjason commented 1 year ago

@yidashi 不谢~ 很高兴能够给你带来一点帮助~

ahKevinXy commented 1 year ago

@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
}
colornote commented 1 year ago

@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版本死活通过不了,去掉又可以

ahKevinXy commented 1 year ago

@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版本死活通过不了,去掉又可以

有例子吗,我现在还是Java 验签 坑的我头发都掉完了

yidashi commented 1 year ago

@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版本死活通过不了,去掉又可以

有例子吗,我现在还是Java 验签 坑的我头发都掉完了

func (s *sZsyh) getUid() []byte {
    ivStr := gstr.SubStr(s.Userid+"0000000000000000", 0, 16)
    iv := []byte(ivStr)
    return iv
}

// CMBSM2SignWithSM3  sign
func (s2 *sZsyh) CMBSM2SignWithSM3(forSignStr string) (string, error) {

    privateKey := s2.GetSm2PrivateKey()
    uid := s2.getUid()

    r, s, err := sm2.Sm2Sign(privateKey, []byte(forSignStr), uid, rand.Reader)
    if err != nil {
        return "", err
    }

    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 gbase64.EncodeToString(buffer.Bytes()), nil
}

// SM3Sum SM3摘要 Hex ToUpper
func SM3Sum(forSignStr string) string {
    h := sm3.New()
    h.Write([]byte(forSignStr))
    return strings.ToUpper(hex.EncodeToString(h.Sum(nil)))
}

// TransHexToSm2PrivateKey 将16进制私钥转换成sm2私钥实例
func (s *sZsyh) GetSm2PrivateKey() *sm2.PrivateKey {
    privateKeyBytes, _ := gbase64.DecodeString(s.PrivateKey)
    HexPrivateKey := hex.EncodeToString(privateKeyBytes)
    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
}

func (s *sZsyh) CMBSM4EncryptWithCBC(data string) []byte {
    // 16 字节的密钥
    key := []byte(s.DuichenKey)
    // 16 字节的 IV (初始向量)
    ivStr := gstr.SubStr(s.Userid+"0000000000000000", 0, 16)
    iv := []byte(ivStr)
    // 待加密的数据
    plaintext := []byte(data)

    // 创建一个 SM4 分组密码块
    block, err := sm4.NewCipher(key)
    if err != nil {
        panic(err)
    }

    // 创建 CBC 分组模式
    mode := cipher.NewCBCEncrypter(block, iv)

    // 对数据进行填充
    paddedPlaintext := make([]byte, len(plaintext))
    copy(paddedPlaintext, plaintext)
    paddingLen := sm4.BlockSize - (len(paddedPlaintext) % sm4.BlockSize)
    for i := 0; i < paddingLen; i++ {
        paddedPlaintext = append(paddedPlaintext, byte(paddingLen))
    }

    // 加密数据
    ciphertext := make([]byte, len(paddedPlaintext))
    mode.CryptBlocks(ciphertext, paddedPlaintext)

    //fmt.Printf("%x", ciphertext)
    return ciphertext
}

func (s *sZsyh) CMBSM4DecryptWithCBC(ciphertext []byte) []byte {
    // 16 字节的密钥
    key := []byte(s.DuichenKey)
    // 16 字节的 IV (初始向量)
    ivStr := gstr.SubStr(s.Userid+"0000000000000000", 0, 16)
    iv := []byte(ivStr)
    // 待解密的数据
    //ciphertext = PKCS7Padding(ciphertext, sm4.BlockSize)
    block, err := sm4.NewCipher(key)
    if err != nil {
        panic(err)
    }

    mode := cipher.NewCBCDecrypter(block, iv)

    plaintext := make([]byte, len(ciphertext))
    mode.CryptBlocks(plaintext, ciphertext)

    return plaintext

}

实在懒得整理了,有几个编码函数用的goframe的,改成原生的就行。能走通,签名和验签函数名都跟java那个sdk同名。大概就这些东西,但愿你改吧改吧能成功

ahKevinXy commented 1 year ago

终于解决了招商银行验签 谢谢大佬们

bigrocs commented 1 year ago

终于解决了招商银行验签 谢谢大佬们

怎么解决的能提供下源码吗 好想userid不对

ahKevinXy commented 1 year ago

终于解决了招商银行验签 谢谢大佬们

怎么解决的能提供下源码吗 好想userid不对

可以的 你加群 问一下,我这边线上跑起来了

bigrocs commented 1 year ago

你好怎么加群

终于解决了招商银行验签 谢谢大佬们

怎么解决的能提供下源码吗 好想userid不对

可以的 你加群 问一下,我这边线上跑起来了

你好怎么加群

ahKevinXy commented 1 year ago

你好怎么加群

终于解决了招商银行验签 谢谢大佬们

怎么解决的能提供下源码吗 好想userid不对

可以的 你加群 问一下,我这边线上跑起来了

你好怎么加群

我加你 qq微信了

bigrocs commented 1 year ago

有兴业搞定的吗 招商和兴业还不一样

DemoLiang commented 1 year ago

我找到了一个可以互相计算hash值,可以对得上得库了

zhouhongxu0422 commented 12 months ago

hxkjason

感谢!卡了一天,用这个过了

tanjl855 commented 7 months ago

你好怎么加群

终于解决了招商银行验签 谢谢大佬们

怎么解决的能提供下源码吗 好想userid不对

可以的 你加群 问一下,我这边线上跑起来了

你好怎么加群

我加你 qq微信了

请问可以提供一下吗,qq:2396514849

tanjl855 commented 7 months ago

终于解决了招商银行验签 谢谢大佬们

大佬,有空帮忙看下啥问题么,一直验签不过

type SZsyh struct {
    PrivateKey string
}

// CMBSM2SignWithSM3  sign
func (s2 *SZsyh) CMBSM2SignWithSM3(forSignStr string, uid []byte) (string, error) {

    privateKey := s2.GetSm2PrivateKey()

    r, s, err := sm2.Sm2Sign(privateKey, []byte(forSignStr), uid, rand.Reader)
    if err != nil {
        return "", err
    }

    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 base64.StdEncoding.EncodeToString(buffer.Bytes()), nil
}

// SM3Sum SM3摘要 Hex ToUpper
func SM3Sum(forSignStr string) string {
    h := sm3.New()
    h.Write([]byte(forSignStr))
    return strings.ToUpper(hex.EncodeToString(h.Sum(nil)))
}

// TransHexToSm2PrivateKey 将16进制私钥转换成sm2私钥实例
func (s *SZsyh) GetSm2PrivateKey() *sm2.PrivateKey {
    privateKeyBytes, _ := base64.StdEncoding.DecodeString(s.PrivateKey)
    d := new(big.Int)
    d.SetBytes(privateKeyBytes)
    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 commented 7 months ago

主页go-cmb 上有联系方式

yiGmMk commented 1 month ago

java Hutool 和 go 之间 sm2 / sm4 互通可以参考下我的,调通了 https://programnotes.cn/crypto/ 主要是保持加密模式一致,ecb,c1c3c2...