Create a CSR with OU separated by comma instead of plus character

114 views Asked by At

I am trying to create a certificate signing request in go using the crypto lib. The problem is it generates the CSR with OU separated by +, i.e.

Subject: O = Example Org, OU = OU1 + OU = OU2, CN = example.com

How can I generate the CSR with OU separated by , like

Subject: O = Example Org, OU = OU1, OU = OU2, CN = example.com

Producing OU separated by + seems to be default behaviour of crypto lib. Can this be done using crypto lib? If no, then is there any other lib that can generate CSR with OU separated by ,

I tried generating the CSR using below code

package main

import (
    "crypto/rand"
    "crypto/rsa"
    "crypto/x509"
    "crypto/x509/pkix"
    "encoding/pem"
    "fmt"
    "os"
)

func main() {
    privKey, err := rsa.GenerateKey(rand.Reader, 2048)
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }

    csrTemplate := x509.CertificateRequest{
        Subject: pkix.Name{
            CommonName:         "example.com",
            Organization:       []string{"Example Org"},
            OrganizationalUnit: []string{"OU1", "OU2"},
        },
        EmailAddresses: []string{"[email protected]"},
    }

    csrBytes, err := x509.CreateCertificateRequest(rand.Reader, &csrTemplate, privKey)
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }

    csrPem := pem.EncodeToMemory(&pem.Block{
        Type:  "CERTIFICATE REQUEST",
        Bytes: csrBytes,
    })

    fmt.Println(string(csrPem))
}

1

There are 1 answers

2
Steffen Ullrich On BEST ANSWER

Neither the '+' nor the ',' are part of the certificate. It is just what is used when providing a human readable string representation of the certificate request.

In detail: your code just prints out a CSR file in PEM format, not a human readable presentation of the certificate request. Looking at this CSR with asn1parse gives:

$ openssl asn1parse -in csr.pem 
   ...       
   37:d=4  hl=2 l=  10 cons: SEQUENCE          
   39:d=5  hl=2 l=   3 prim: OBJECT            :organizationalUnitName
   44:d=5  hl=2 l=   3 prim: PRINTABLESTRING   :OU1
   49:d=4  hl=2 l=  10 cons: SEQUENCE          
   51:d=5  hl=2 l=   3 prim: OBJECT            :organizationalUnitName
   56:d=5  hl=2 l=   3 prim: PRINTABLESTRING   :OU2
   61:d=3  hl=2 l=  20 cons: SET    

So, these are separate objects and not a combined string with a '+' between. This '+' instead comes when displaying the certificate request using req:

$ openssl req -in csr.pem -text 
Certificate Request:
    Data:
        Version: 1 (0x0)
        Subject: O = Example Org, OU = OU1 + OU = OU2, CN = example.com

Which separator is used here can actually be kind of configured. See openssl-namedisplay-options and look for sep_comma_plus_space, which is the default separator. To cite the documentation:

The first word is used between the Relative Distinguished Names (RDNs) and the second is between multiple Attribute Value Assertions (AVAs). Multiple AVAs are very rare and their use is discouraged.

So there you have it: a comma is used between different RDN (i.e. O, OU, CN, ...) while a plus is used between multiple AVA inside the same RDN (like multiple OU). Also, using multiple AVA is discouraged anyway.