Search code examples
gox509csr

Create a CSR with specific subject order in go


I am trying to create a certificate signing request in go using the crypto lib. The CSR produced by the has the subject as "Subject: C = IN, L = loc, O = Example Org, OU = OU1 + OU = OU2, CN = example.com". I want to change the order of the subject as "Subject: C = IN,O = Example Org, OU = OU1 + OU = OU2, L = loc, CN = example.com".

I have produced 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{
            Country:            []string{"IN"},
            Organization:       []string{"Example Org"},
            OrganizationalUnit: []string{"OU1", "OU2"},
            Locality:           []string{"loc"},
            CommonName:         "example.com",
        },
        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))
}

This code produces CSR with subject as "Subject: C = IN, L = loc, O = Example Org, OU = OU1 + OU = OU2, CN = example.com". I can generate the CSR with required subject order using openssl below command

openssl req -new -sha256 -key my-private-key.pem -out my-csr1.pem -subj '/C=IN/O=Org/OU=OU1/OU=OU2/L=loc/CN=example.com'

How to do the same in go?


Solution

  • It is unclear to me why you want to have the RDN inside the subject in this specific order. I would argue, that any software which relies on a specific order is somewhat broken. Of course, broken software exists and sometimes the only way is to work around it.

    There is a way to do this using golang too. You cannot simply use the matching field names in pkix.Name though since these will be serialized in a fixed order. To get your own order you would need to use ExtraNames and then provide the RDN in the order you require:

        var (
            oidCountry            = []int{2, 5, 4, 6}
            oidOrganization       = []int{2, 5, 4, 10}
            oidOrganizationalUnit = []int{2, 5, 4, 11}
            oidCommonName         = []int{2, 5, 4, 3}
            oidLocality           = []int{2, 5, 4, 7}
        )
        csrTemplate := x509.CertificateRequest{
            Subject: pkix.Name{
                ExtraNames: []pkix.AttributeTypeAndValue{
                    { oidCountry, "IN" },
                    { oidOrganization, "Example Org" },
                    { oidOrganizationalUnit, "OU1" },
                    { oidOrganizationalUnit, "OU2" },
                    { oidLocality, "loc" },
                    { oidCommonName, "example.com" },
                },
            },
            EmailAddresses: []string{"[email protected]"},
        }