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{"test@example.com"}, } 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?
In Go, you can achieve the desired subject order by manually constructing the pkix.Name structure in the desired order. The pkix.Name structure has a field called ExtraNames, which is a slice of AttributeTypeAndValue structures. You can use this field to specify the order of subject attributes. Here’s an example:
pkix.Name
ExtraNames
AttributeTypeAndValue
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{ ExtraNames: []pkix.AttributeTypeAndValue{ {Type: oidCountry, Value: "IN"}, {Type: oidOrganization, Value: "Example Org"}, {Type: oidOrganizationalUnit, Value: "OU1"}, {Type: oidOrganizationalUnit, Value: "OU2"}, {Type: oidLocality, Value: "loc"}, {Type: oidCommonName, Value: "example.com"}, }, }, EmailAddresses: []string{"test@example.com"}, } 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)) } // OID constants for subject attributes var ( oidCountry = []int{2, 5, 4, 6} oidOrganization = []int{2, 5, 4, 10} oidOrganizationalUnit = []int{2, 5, 4, 11} oidLocality = []int{2, 5, 4, 7} oidCommonName = []int{2, 5, 4, 3} )
In this example, the ExtraNames slice is populated with AttributeTypeAndValue elements in the order you desire. The oidCountry, oidOrganization, etc., are constants representing the OIDs (Object Identifiers) for the respective attributes. This approach allows you to control the order of the subject attributes in the resulting CSR.
oidCountry
oidOrganization