diff --git a/docs/pkcs7.md b/docs/pkcs7.md index bdc63fe..6281ce4 100644 --- a/docs/pkcs7.md +++ b/docs/pkcs7.md @@ -55,6 +55,10 @@ 3. 如果签名数据中不包含证书项,则手动设置验签证书(参考```TestSkipCertificates```); 4. 调用```Verify```或```VerifyWithChain```方法。 +#### 特殊方法 +```DegenerateCertificate```,退化成签名数据中只包含证书,目前没有使用SM2 OID的方法,如果需要可以请求添加。可以参考```TestDegenerateCertificate```和```TestParseSM2CertificateChain```。 + + ### 签名及数字信封数据(Signed and Enveloped Data) 签名和数字信封数据,使用场景较少,有些实现用它来传输私钥(譬如www.gmcert.org)。具体请参考```sign_enveloped_test.go```。 diff --git a/pkcs7/sign.go b/pkcs7/sign.go index 65e22a2..1ed0a85 100644 --- a/pkcs7/sign.go +++ b/pkcs7/sign.go @@ -37,7 +37,7 @@ func NewSignedData(data []byte) (*SignedData, error) { } ci := contentInfo{ ContentType: OIDData, - Content: asn1.RawValue{Class: 2, Tag: 0, Bytes: content, IsCompound: true}, + Content: asn1.RawValue{Class: asn1.ClassContextSpecific, Tag: 0, Bytes: content, IsCompound: true}, } sd := signedData{ ContentInfo: ci, diff --git a/smx509/csr_rsp.go b/smx509/csr_rsp.go index c875dfe..07a2b61 100644 --- a/smx509/csr_rsp.go +++ b/smx509/csr_rsp.go @@ -20,8 +20,16 @@ type CSRResponse struct { EncryptCerts []*Certificate } +// GM/T 0092-2020 Specification of certificate request syntax based on SM2 cryptographic algorithm. +// Section 8 and Appendix A +// +// CSRResponse ::= SEQUENCE { +// signCertificate CertificateSet, +// encryptedPrivateKey [0] SM2EnvelopedKey OPTIONAL, +// encryptCertificate [1] CertificateSet OPTIONAL +// } type tbsCSRResponse struct { - SignCerts rawCertificates + SignCerts []asn1.RawValue `asn1:"set"` // SignCerts ::= SET OF Certificate EncryptedPrivateKey asn1.RawValue `asn1:"optional,tag:0"` EncryptCerts rawCertificates `asn1:"optional,tag:1"` } @@ -39,9 +47,14 @@ func ParseCSRResponse(signPrivateKey *sm2.PrivateKey, der []byte) (CSRResponse, if err != nil || len(rest) > 0 { return result, errors.New("smx509: invalid CSRResponse asn1 data") } - signCerts, err := resp.SignCerts.Parse() - if err != nil || len(signCerts) == 0 { - return result, errors.New("smx509: invalid sign certificates") + + signCerts := make([]*Certificate, len(resp.SignCerts)) + for i, rawCert := range resp.SignCerts { + signCert, err := ParseCertificate(rawCert.FullBytes) + if err != nil { + return result, err + } + signCerts[i] = signCert } // check sign public key against the private key @@ -98,13 +111,16 @@ func MarshalCSRResponse(signCerts []*Certificate, encryptPrivateKey *sm2.Private } resp := tbsCSRResponse{} - resp.SignCerts = marshalCertificates(signCerts) + resp.SignCerts = make([]asn1.RawValue, 0, len(signCerts)) + for _, cert := range signCerts { + resp.SignCerts = append(resp.SignCerts, asn1.RawValue{FullBytes: cert.Raw}) + } if encryptPrivateKey != nil && len(encryptCerts) > 0 { privateKeyBytes, err := sm2.MarshalEnvelopedPrivateKey(rand.Reader, signPubKey, encryptPrivateKey) if err != nil { return nil, err } - resp.EncryptedPrivateKey = asn1.RawValue{Class: 2, Tag: 0, IsCompound: true, Bytes: privateKeyBytes} + resp.EncryptedPrivateKey = asn1.RawValue{Class: asn1.ClassContextSpecific, Tag: 0, IsCompound: true, Bytes: privateKeyBytes} resp.EncryptCerts = marshalCertificates(encryptCerts) } return asn1.Marshal(resp) @@ -124,7 +140,7 @@ func marshalCertificates(certs []*Certificate) rawCertificates { // RawContent, we have to encode it into the RawContent. If its missing, // then `asn1.Marshal()` will strip out the certificate wrapper instead. func marshalCertificateBytes(certs []byte) (rawCertificates, error) { - var val = asn1.RawValue{Bytes: certs, Class: 2, Tag: 0, IsCompound: true} + var val = asn1.RawValue{Bytes: certs, Class: asn1.ClassContextSpecific, Tag: 0, IsCompound: true} b, err := asn1.Marshal(val) if err != nil { return rawCertificates{}, err diff --git a/smx509/csr_rsp_test.go b/smx509/csr_rsp_test.go index e27aaa1..89982a8 100644 --- a/smx509/csr_rsp_test.go +++ b/smx509/csr_rsp_test.go @@ -113,7 +113,6 @@ func TestMarshalCSRResponse(t *testing.T) { // Call the function result, err := smx509.MarshalCSRResponse([]*smx509.Certificate{pairs[0].Certificate, pairs[2].Certificate}, encPrivKey, []*smx509.Certificate{pairs[1].Certificate, pairs[2].Certificate}) - // Check the result if err != nil { t.Errorf("Unexpected error: %v", err) @@ -154,17 +153,17 @@ func TestMarshalCSRResponse(t *testing.T) { } _, err = smx509.MarshalCSRResponse(nil, nil, nil) - if err == nil || err.Error() != "smx509: no sign certificate" { + if err == nil || err.Error() != "smx509: no sign certificate" { t.Errorf("Unexpected error: %v", err) } _, err = smx509.MarshalCSRResponse([]*smx509.Certificate{pairs[0].Certificate, pairs[2].Certificate}, encPrivKey, nil) - if err == nil || err.Error() != "smx509: missing encrypt certificate" { + if err == nil || err.Error() != "smx509: missing encrypt certificate" { t.Errorf("Unexpected error: %v", err) } _, err = smx509.MarshalCSRResponse([]*smx509.Certificate{pairs[0].Certificate, pairs[2].Certificate}, encPrivKey, []*smx509.Certificate{pairs[2].Certificate}) - if err == nil || err.Error() != "smx509: encrypt key pair mismatch" { + if err == nil || err.Error() != "smx509: encrypt key pair mismatch" { t.Errorf("Unexpected error: %v", err) } }