Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

请问SM2签名方法中的 random io.Reader 参数应该传什么? #208

Open
xpsuper opened this issue Sep 26, 2024 · 0 comments
Open

Comments

@xpsuper
Copy link

xpsuper commented Sep 26, 2024

请问
func Sm2Sign(priv *PrivateKey, msg, uid []byte, random io.Reader) (r, s *big.Int, err error) 中的 random io.Reader 参数应该传什么?

然后好心人帮忙看下应该怎么翻译 java 中的 SM2加签验签,我写的 go 加签验签一直对不上,头大

JAVA:

package com.allinpay.sign;

import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;
import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Base64;
import com.alibaba.fastjson.JSONObject;

public class DemoSM2Utils
{
    /** 算法常量:SM3withSM2 */
    public static final String ALGORITHM_SM3SM2_BCPROV = "SM3withSM2";

    static
    {
        Security.addProvider(new BouncyCastleProvider());
    }

    /** 从字符串读取私钥-目前支持PKCS8(keystr为BASE64格式) */
    public static PrivateKey privKeySM2FromBase64Str(String keystr) throws Exception
    {
        KeyFactory keyFactory = KeyFactory.getInstance("EC");
        return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(Base64.decode(keystr)));
    }

    /** 从字符串读取RSA公钥(keystr为BASE64格式) */
    public static PublicKey pubKeySM2FromBase64Str(String keystr) throws Exception
    {
        KeyFactory keyFactory = KeyFactory.getInstance("EC");
        return keyFactory.generatePublic(new X509EncodedKeySpec(Base64.decode(keystr)));
    }

    public static String sign(PrivateKey privateKey, String text) throws Exception
    {
        Signature signature = Signature.getInstance(ALGORITHM_SM3SM2_BCPROV, "BC");
        signature.initSign(privateKey);
        byte[] plainText = text.getBytes(StandardCharsets.UTF_8);
        signature.update(plainText);
        byte[] signatureValue = signature.sign();
        return Base64.toBase64String(signatureValue);
    }

    public static boolean verify(PublicKey publicKey, String text, String sign) throws Exception
    {
        if (isEmpty(sign))
        {
            return false;
        }
        Signature signature = Signature.getInstance(ALGORITHM_SM3SM2_BCPROV, "BC");
        signature.initVerify(publicKey);
        signature.update(text.getBytes(StandardCharsets.UTF_8));
        byte[] signed = Base64.decode(sign);
        return signature.verify(signed);
    }

    public static boolean isEmpty(String str)
    {
        return str == null || "".equals(str) || "".equals(str.trim());
    }
}

Golang :

package allinpay2

import (
	"bytes"
	"crypto/rand"
	"encoding/base64"
	"encoding/pem"
	"fmt"
	"github.com/tjfoc/gmsm/sm2"
	"github.com/tjfoc/gmsm/x509"
	"math/big"
)

func Sign(privateKey string, text string) (string, error) {
	key, err := privateKeyFromBase64Str(privateKey)
	if err != nil {
		return "", err
	}

	r, s, err := sm2.Sm2Sign(key, stl.StringToBytes(text), default_uid, rand.Reader)
	if err != nil {
		return "", err
	}

	var buffer bytes.Buffer
	buffer.Write(r.Bytes())
	buffer.Write(s.Bytes())

	signature := base64.StdEncoding.EncodeToString(buffer.Bytes())
	return signature, nil
}

// Verify signature using SM2 public key
func Verify(publicKey string, text, signBase64 string) (bool, error) {
	if stl.IsEmpty(signBase64) {
		return false, nil
	}

	key, err := publicKeySM2FromBase64Str(publicKey)
	if err != nil {
		return false, err
	}

	signature, err := base64.StdEncoding.DecodeString(signBase64)
	if err != nil {
		return false, err
	}

	l := len(signature)
	br := signature[:l/2]
	bs := signature[l/2:]

	var ri, si big.Int
	r := ri.SetBytes(br)
	s := si.SetBytes(bs)

	return sm2.Sm2Verify(key, []byte(text), default_uid, r, s), nil
}

/***** Below are the helper functions *****/
var (
	default_uid = []byte{0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38}
)

func privateKeyFromBase64Str(keyStr string) (*sm2.PrivateKey, error) {
	pemBytes, err := base64.StdEncoding.DecodeString(keyStr)
	if err != nil {
		return nil, err
	}
	//block, _ := pem.Decode(pemBytes)
	//if block == nil {
	//	return nil, fmt.Errorf("failed to parse PEM block containing the key")
	//}
	return x509.ParsePKCS8UnecryptedPrivateKey(pemBytes)
}

// Decode base64 string to SM2 public key
func publicKeySM2FromBase64Str(keyStr string) (*sm2.PublicKey, error) {
	pemBytes, err := base64.StdEncoding.DecodeString(keyStr)
	if err != nil {
		return nil, err
	}
	block, _ := pem.Decode(pemBytes)
	if block == nil {
		return nil, fmt.Errorf("failed to parse PEM block containing the key")
	}
	genericPublicKey, err := x509.ParsePKIXPublicKey(pemBytes)
	if err != nil {
		return nil, err
	}
	return genericPublicKey.(*sm2.PublicKey), nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant