Skip to content

Commit

Permalink
support cfca certificate request #286
Browse files Browse the repository at this point in the history
  • Loading branch information
emmansun authored Dec 10, 2024
1 parent 1d894ef commit df3db92
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 3 deletions.
7 changes: 7 additions & 0 deletions cfca/pkcs10.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,17 @@ 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.
// The challenge password is basically a shared-secret nonce between you and CFCA, embedded in the CSR.
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)
}
12 changes: 10 additions & 2 deletions cfca/pkcs10_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (
"testing"

"github.com/emmansun/gmsm/sm2"
"github.com/emmansun/gmsm/smx509"
)

func TestCreateCertificateRequest(t *testing.T) {
Expand Down Expand Up @@ -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")
}
}
54 changes: 54 additions & 0 deletions smx509/cfca_csr.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package smx509

import (
"bytes"
"crypto"
"crypto/ecdsa"
"crypto/x509"
Expand Down Expand Up @@ -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])
}
}
}
}
8 changes: 7 additions & 1 deletion smx509/cfca_csr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
}
}

0 comments on commit df3db92

Please sign in to comment.