Skip to content

Commit

Permalink
Merge pull request #1312 from kongweiguo/add-csr-der
Browse files Browse the repository at this point in the history
  • Loading branch information
nickysemenza committed Jun 28, 2023
2 parents 707f415 + 6619c79 commit f0549e3
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 2 deletions.
15 changes: 13 additions & 2 deletions csr/csr.go
Expand Up @@ -408,9 +408,9 @@ func Regenerate(priv crypto.Signer, csr []byte) ([]byte, error) {
return x509.CreateCertificateRequest(rand.Reader, req, priv)
}

// Generate creates a new CSR from a CertificateRequest structure and
// GenerateDER creates a new CSR(ASN1 DER encoded) from a CertificateRequest structure and
// an existing key. The KeyRequest field is ignored.
func Generate(priv crypto.Signer, req *CertificateRequest) (csr []byte, err error) {
func GenerateDER(priv crypto.Signer, req *CertificateRequest) (csr []byte, err error) {
sigAlgo := helpers.SignerAlgo(priv)
if sigAlgo == x509.UnknownSignatureAlgorithm {
return nil, cferr.New(cferr.PrivateKeyError, cferr.Unavailable)
Expand Down Expand Up @@ -466,6 +466,17 @@ func Generate(priv crypto.Signer, req *CertificateRequest) (csr []byte, err erro
err = cferr.Wrap(cferr.CSRError, cferr.BadRequest, err)
return
}
return
}

// Generate creates a new CSR(PEM encoded) from a CertificateRequest structure and
// an existing key. The KeyRequest field is ignored.
func Generate(priv crypto.Signer, req *CertificateRequest) (csr []byte, err error) {

csr, err = GenerateDER(priv, req)
if err != nil {
return
}
block := pem.Block{
Type: "CERTIFICATE REQUEST",
Bytes: csr,
Expand Down
53 changes: 53 additions & 0 deletions csr/csr_test.go
Expand Up @@ -705,6 +705,59 @@ func TestGenerate(t *testing.T) {
}
}

func TestGenerateASN1(t *testing.T) {
var req = &CertificateRequest{
Names: []Name{
{
C: "US",
ST: "California",
L: "San Francisco",
O: "CloudFlare",
OU: "Systems Engineering",
},
},
CN: "cloudflare.com",
Hosts: []string{"cloudflare.com", "www.cloudflare.com", "192.168.0.1", "jdoe@example.com", "https://www.cloudflare.com"},
KeyRequest: &KeyRequest{"ecdsa", 256},
}

key, err := req.KeyRequest.Generate()
if err != nil {
t.Fatalf("%v", err)
}

priv, ok := key.(crypto.Signer)
if !ok {
t.Fatal("Private key is not a signer.")
}

csrDER, err := GenerateDER(priv, req)
if err != nil {
t.Fatalf("%v", err)
}

csr, err := helpers.ParseCSRDER(csrDER)
if err != nil {
t.Fatalf("%v", err)
}

if len(csr.DNSNames) != 2 {
t.Fatal("SAN parsing error")
}

if len(csr.IPAddresses) != 1 {
t.Fatal("SAN parsing error")
}

if len(csr.EmailAddresses) != 1 {
t.Fatal("SAN parsing error")
}

if len(csr.URIs) != 1 {
t.Fatal("SAN parsing error")
}
}

// TestReGenerate ensures Regenerate() is abel to use the provided CSR as a template for signing a new
// CSR using priv.
func TestReGenerate(t *testing.T) {
Expand Down
17 changes: 17 additions & 0 deletions helpers/helpers.go
Expand Up @@ -457,6 +457,23 @@ func ParseCSRPEM(csrPEM []byte) (*x509.CertificateRequest, error) {
return csrObject, nil
}

// ParseCSRDER parses a PEM-encoded certificate signing request.
// It does not check the signature. This is useful for dumping data from a CSR
// locally.
func ParseCSRDER(csrDER []byte) (*x509.CertificateRequest, error) {
csrObject, err := x509.ParseCertificateRequest(csrDER)
if err != nil {
return nil, err
}

err = csrObject.CheckSignature()
if err != nil {
return nil, err
}

return csrObject, nil
}

// SignerAlgo returns an X.509 signature algorithm from a crypto.Signer.
func SignerAlgo(priv crypto.Signer) x509.SignatureAlgorithm {
switch pub := priv.Public().(type) {
Expand Down

0 comments on commit f0549e3

Please sign in to comment.