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:
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.