smx509: fix CSRResponse sign certs handle issue

This commit is contained in:
Sun Yimin 2024-06-18 11:43:20 +08:00 committed by GitHub
parent a1de6312b4
commit 0445d16e97
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 31 additions and 12 deletions

View File

@ -55,6 +55,10 @@
3. 如果签名数据中不包含证书项,则手动设置验签证书(参考```TestSkipCertificates``` 3. 如果签名数据中不包含证书项,则手动设置验签证书(参考```TestSkipCertificates```
4. 调用```Verify```或```VerifyWithChain```方法。 4. 调用```Verify```或```VerifyWithChain```方法。
#### 特殊方法
```DegenerateCertificate```退化成签名数据中只包含证书目前没有使用SM2 OID的方法如果需要可以请求添加。可以参考```TestDegenerateCertificate```和```TestParseSM2CertificateChain```。
### 签名及数字信封数据Signed and Enveloped Data ### 签名及数字信封数据Signed and Enveloped Data
签名和数字信封数据使用场景较少有些实现用它来传输私钥譬如www.gmcert.org。具体请参考```sign_enveloped_test.go```。 签名和数字信封数据使用场景较少有些实现用它来传输私钥譬如www.gmcert.org。具体请参考```sign_enveloped_test.go```。

View File

@ -37,7 +37,7 @@ func NewSignedData(data []byte) (*SignedData, error) {
} }
ci := contentInfo{ ci := contentInfo{
ContentType: OIDData, 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{ sd := signedData{
ContentInfo: ci, ContentInfo: ci,

View File

@ -20,8 +20,16 @@ type CSRResponse struct {
EncryptCerts []*Certificate 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 { type tbsCSRResponse struct {
SignCerts rawCertificates SignCerts []asn1.RawValue `asn1:"set"` // SignCerts ::= SET OF Certificate
EncryptedPrivateKey asn1.RawValue `asn1:"optional,tag:0"` EncryptedPrivateKey asn1.RawValue `asn1:"optional,tag:0"`
EncryptCerts rawCertificates `asn1:"optional,tag:1"` EncryptCerts rawCertificates `asn1:"optional,tag:1"`
} }
@ -39,9 +47,14 @@ func ParseCSRResponse(signPrivateKey *sm2.PrivateKey, der []byte) (CSRResponse,
if err != nil || len(rest) > 0 { if err != nil || len(rest) > 0 {
return result, errors.New("smx509: invalid CSRResponse asn1 data") return result, errors.New("smx509: invalid CSRResponse asn1 data")
} }
signCerts, err := resp.SignCerts.Parse()
if err != nil || len(signCerts) == 0 { signCerts := make([]*Certificate, len(resp.SignCerts))
return result, errors.New("smx509: invalid sign certificates") 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 // check sign public key against the private key
@ -98,13 +111,16 @@ func MarshalCSRResponse(signCerts []*Certificate, encryptPrivateKey *sm2.Private
} }
resp := tbsCSRResponse{} 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 { if encryptPrivateKey != nil && len(encryptCerts) > 0 {
privateKeyBytes, err := sm2.MarshalEnvelopedPrivateKey(rand.Reader, signPubKey, encryptPrivateKey) privateKeyBytes, err := sm2.MarshalEnvelopedPrivateKey(rand.Reader, signPubKey, encryptPrivateKey)
if err != nil { if err != nil {
return nil, err 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) resp.EncryptCerts = marshalCertificates(encryptCerts)
} }
return asn1.Marshal(resp) 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, // RawContent, we have to encode it into the RawContent. If its missing,
// then `asn1.Marshal()` will strip out the certificate wrapper instead. // then `asn1.Marshal()` will strip out the certificate wrapper instead.
func marshalCertificateBytes(certs []byte) (rawCertificates, error) { 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) b, err := asn1.Marshal(val)
if err != nil { if err != nil {
return rawCertificates{}, err return rawCertificates{}, err

View File

@ -113,7 +113,6 @@ func TestMarshalCSRResponse(t *testing.T) {
// Call the function // Call the function
result, err := smx509.MarshalCSRResponse([]*smx509.Certificate{pairs[0].Certificate, pairs[2].Certificate}, encPrivKey, []*smx509.Certificate{pairs[1].Certificate, pairs[2].Certificate}) result, err := smx509.MarshalCSRResponse([]*smx509.Certificate{pairs[0].Certificate, pairs[2].Certificate}, encPrivKey, []*smx509.Certificate{pairs[1].Certificate, pairs[2].Certificate})
// Check the result // Check the result
if err != nil { if err != nil {
t.Errorf("Unexpected error: %v", err) t.Errorf("Unexpected error: %v", err)