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

国密算法p7签名报错问题 #303

Closed
tianfw-code opened this issue Feb 14, 2025 · 4 comments
Closed

国密算法p7签名报错问题 #303

tianfw-code opened this issue Feb 14, 2025 · 4 comments

Comments

@tianfw-code
Copy link

p7签名使用sm2算法时, 红框处hasher 为 crypto.Hash(0), hasher.New()会报错,麻烦修复一下,谢谢。
Image

@emmansun
Copy link
Owner

这个是内部函数,请提供测试用例,谢谢!

@tianfw-code
Copy link
Author

package sign

import (
	"crypto"
	"crypto/rand"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/pem"
	"io"
	"log"
	"math/big"
	"os"
	"strings"
	"testing"
	"time"

	"github.com/emmansun/gmsm/pkcs7"
	"github.com/emmansun/gmsm/sm2"
	"github.com/emmansun/gmsm/sm3"
	"github.com/emmansun/gmsm/smx509"
	"github.com/pkg/errors"
)

type CertKeyPair struct {
	Certificate *smx509.Certificate
	PrivateKey  crypto.PrivateKey
}

func CreateTestCertificateByIssuer(name string, issuer *CertKeyPair, sigAlg x509.SignatureAlgorithm, keyUsage x509.KeyUsage, isCA bool) (*CertKeyPair, error) {
	var (
		err        error
		priv       crypto.PrivateKey
		derCert    []byte
		issuerCert *smx509.Certificate
		issuerKey  crypto.PrivateKey
	)
	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 32)
	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
	if err != nil {
		return nil, errors.WithStack(err)
	}

	template := x509.Certificate{
		SerialNumber: serialNumber,
		Subject: pkix.Name{
			CommonName:   name,
			Organization: []string{"Acme Co"},
		},
		NotBefore:   time.Now().Add(-1 * time.Second),
		NotAfter:    time.Now().AddDate(1, 0, 0),
		KeyUsage:    keyUsage,
		ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageEmailProtection},
	}
	if issuer != nil {
		issuerCert = issuer.Certificate
		issuerKey = issuer.PrivateKey
	}

	switch sigAlg {

	case smx509.SM2WithSM3:
		priv, err = sm2.GenerateKey(rand.Reader)
		if err != nil {
			return nil, errors.WithStack(err)
		}
	}
	if isCA {
		template.IsCA = true
		template.KeyUsage |= x509.KeyUsageCertSign
		template.BasicConstraintsValid = true
	}
	if issuer == nil {
		// no issuer given,make this a self-signed root cert
		issuerCert = (*smx509.Certificate)(&template)
		issuerKey = priv
	}

	log.Println("creating cert", name, "issued by", issuerCert.Subject.CommonName, "with sigalg", sigAlg)
	switch pkey := priv.(type) {
	case *sm2.PrivateKey:
		derCert, err = smx509.CreateCertificate(rand.Reader, &template, (*x509.Certificate)(issuerCert), pkey.Public(), issuerKey)
	}
	if err != nil {
		return nil, errors.WithStack(err)
	}
	if len(derCert) == 0 {
		return nil, errors.Errorf("no certificate created, probably due to wrong keys. types were %T and %T", priv, issuerKey)
	}
	cert, err := smx509.ParseCertificate(derCert)
	if err != nil {
		return nil, errors.WithStack(err)
	}
	pem.Encode(os.Stdout, &pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw})
	return &CertKeyPair{
		Certificate: cert,
		PrivateKey:  priv,
	}, nil
}

func createSM2Certificates() (caCert, cert *CertKeyPair, err error) {
	ca, err := CreateTestCertificateByIssuer("Eddard Stark", nil, smx509.SM2WithSM3, x509.KeyUsageDigitalSignature, true)
	if err != nil {
		return
	}
	cert, err = CreateTestCertificateByIssuer("Jon Snow", ca, smx509.SM2WithSM3, x509.KeyUsageDigitalSignature, false)
	return
}

func TestPkcs7(t *testing.T) {
	type signOptions struct {
		Hash crypto.Hash
	}

	type args struct {
		r       io.Reader
		options signOptions
	}

	tests := []struct {
		name string
		args args
	}{
		// TODO: Add test cases.
		{name: "SM3", args: args{r: strings.NewReader("test digital sign"), options: signOptions{Hash: 0}}},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			_, certKeyPair, err := createSM2Certificates()
			if err != nil {
				log.Fatalf("createCertificates:%v", err)
			}

			var toBeSigned *pkcs7.SignedData
			hasher := sm3.New()
			_, err = hasher.Write([]byte{0x31, 0x32, 0x33})
			if err != nil {
				log.Fatalf("hasher.Write:%v", err)
			}
			dataHash := hasher.Sum(nil)
			toBeSigned, err = pkcs7.NewSMSignedDataWithDigest(dataHash)
			if err != nil {
				log.Fatalf("pkcs7.NewSMSignedDataWithDigest:%v", err)
			}

			toBeSigned.SetDigestAlgorithm(pkcs7.OIDDigestAlgorithmSM2SM3)
			err = toBeSigned.AddSignerChain(certKeyPair.Certificate, certKeyPair.PrivateKey, nil, pkcs7.SignerInfoConfig{})
			if err != nil {
				log.Fatalf("pkcs7.AddSignerChain:%v", err)
			}

			// Detach signature
			toBeSigned.Detach()

			_, err = toBeSigned.Finish()
			if err != nil {
				log.Fatalf("pkcs7.Finish:%v", err)
			}

		})
	}

}

@emmansun
Copy link
Owner

哪里有问题?除了

  • toBeSigned.SetDigestAlgorithm(pkcs7.OIDDigestAlgorithmSM2SM3),因为 pkcs7.NewSMSignedDataWithDigest已经默认使用OIDDigestAlgorithmSM3了。
  • toBeSigned.Detach()也没有必要,直接签hash值就是detached。

@tianfw-code
Copy link
Author

哦,是因为我这边的项目在调用的时候,对crypto.Hash=0 进行了注册,所以在signData()签名时在 hasher.Available()结果为true,所以报错了,这边去掉注册后就成功了。感谢答疑。

const(
   SM3 crypto.Hash=0
)
func init(){
     crypto.RegisterHash(SM3, sm3.New)
}

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

2 participants