support cfca certificate request #286

This commit is contained in:
Sun Yimin 2024-12-10 10:13:51 +08:00 committed by GitHub
parent 1d894ef955
commit df3db923c6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 78 additions and 3 deletions

View File

@ -11,6 +11,8 @@ import (
"github.com/emmansun/gmsm/smx509"
)
type CertificateRequest = smx509.CertificateRequestCFCA
// CreateCertificateRequest creates a new certificate request based on a template.
// The following members of template are used: Subject.
// The certPriv is the private key for the certificate, and the tmpPriv is the temporary private key for returning encryption key decryption.
@ -18,3 +20,8 @@ import (
func CreateCertificateRequest(rand io.Reader, template *x509.CertificateRequest, certPriv, tmpPriv any, challengePassword string) ([]byte, error) {
return smx509.CreateCFCACertificateRequest(rand, template, certPriv, tmpPriv, challengePassword)
}
// ParseCertificateRequest parses a certificate request from the given DER data.
func ParseCertificateRequest(der []byte) (*CertificateRequest, error) {
return smx509.ParseCFCACertificateRequest(der)
}

View File

@ -13,7 +13,6 @@ import (
"testing"
"github.com/emmansun/gmsm/sm2"
"github.com/emmansun/gmsm/smx509"
)
func TestCreateCertificateRequest(t *testing.T) {
@ -57,11 +56,20 @@ func TestCreateCertificateRequest(t *testing.T) {
if err != nil {
t.Fatal(err)
}
csr, err := smx509.ParseCertificateRequest(csrDer)
csr, err := ParseCertificateRequest(csrDer)
if err != nil {
t.Fatal(err)
}
if csr.Subject.CommonName != "certRequisition" {
t.Fatal("common name not match")
}
if csr.Subject.CommonName != "certRequisition" {
t.Fatal("common name not match")
}
if csr.ChallengePassword != "111111" {
t.Fatal("challenge password not match")
}
if csr.TmpPublicKey == nil {
t.Fatal("tmp public key not match")
}
}

View File

@ -5,6 +5,7 @@
package smx509
import (
"bytes"
"crypto"
"crypto/ecdsa"
"crypto/x509"
@ -162,3 +163,56 @@ func buildTmpPublicKeyAttr(rawAttributes []asn1.RawValue, tmpPriv any) ([]asn1.R
return append(rawAttributes, rawValue), nil
}
// CertificateRequestCFCA represents a CFCA certificate request.
type CertificateRequestCFCA struct {
CertificateRequest
ChallengePassword string
TmpPublicKey any
}
// ParseCFCACertificateRequest parses a CFCA certificate request from the given DER data.
func ParseCFCACertificateRequest(asn1Data []byte) (*CertificateRequestCFCA, error) {
var csr certificateRequest
rest, err := asn1.Unmarshal(asn1Data, &csr)
if err != nil {
return nil, err
} else if len(rest) != 0 {
return nil, asn1.SyntaxError{Msg: "trailing data"}
}
inner, err := parseCertificateRequest(&csr)
if err != nil {
return nil, err
}
out := &CertificateRequestCFCA{
CertificateRequest: *inner,
}
parseCFCAAttributes(out, csr.TBSCSR.RawAttributes)
return out, nil
}
func parseCFCAAttributes(out *CertificateRequestCFCA, rawAttributes []asn1.RawValue) {
var value struct {
Type asn1.ObjectIdentifier
Value asn1.RawValue
}
for _, attr := range rawAttributes {
if _, err := asn1.Unmarshal(attr.FullBytes, &value); err != nil {
continue
}
switch {
case value.Type.Equal(oidChallengePassword):
asn1.Unmarshal(value.Value.FullBytes, &out.ChallengePassword)
case value.Type.Equal(oidTmpPublicKey):
var keyBytes []byte
asn1.Unmarshal(value.Value.FullBytes, &keyBytes)
if len(keyBytes) == 136 && bytes.Equal(tmpPublicKeyPrefix, keyBytes[:8]) {
// parse the public key
copy(keyBytes[40:72], keyBytes[72:104])
out.TmpPublicKey, _ = sm2.NewPublicKey(keyBytes[8:72])
}
}
}
}

View File

@ -56,11 +56,17 @@ func TestCreateCFCACertificateRequest(t *testing.T) {
if err != nil {
t.Fatal(err)
}
csr, err := ParseCertificateRequest(csrDer)
csr, err := ParseCFCACertificateRequest(csrDer)
if err != nil {
t.Fatal(err)
}
if csr.Subject.CommonName != "certRequisition" {
t.Fatal("common name not match")
}
if csr.ChallengePassword != "111111" {
t.Fatal("challenge password not match")
}
if csr.TmpPublicKey == nil {
t.Fatal("tmp public key not match")
}
}