package main import ( "crypto/ecdsa" "crypto/elliptic" "crypto/rand" "crypto/x509" "crypto/x509/pkix" "encoding/pem" "log" "os") func main() { key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { log.Fatal(err) } template := &x509.CertificateRequest{ Subject: pkix.Name{ Country: []string{"US"}, Organization: []string{"Example Corp"}, CommonName: "api.example.com", }, DNSNames: []string{"api.example.com", "www.example.com"}, // becomes the SAN extension SignatureAlgorithm: x509.ECDSAWithSHA256, } der, err := x509.CreateCertificateRequest(rand.Reader, template, key) if err != nil { log.Fatal(err) } keyDER, err := x509.MarshalPKCS8PrivateKey(key) if err != nil { log.Fatal(err) } if err := os.WriteFile("key.pem", pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: keyDER}), 0o600); err != nil { log.Fatal(err) } if err := os.WriteFile("csr.pem", pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE REQUEST", Bytes: der}), 0o644); err != nil { log.Fatal(err) }} How it works
ecdsa.GenerateKey(elliptic.P256(), rand.Reader)creates the key.pkix.Nameholds the subject;CountryandOrganizationare slices because a name may repeat an attribute.DNSNamesbecomes the subjectAltName extension;IPAddresses,EmailAddressesandURIscover the other SAN types.x509.CreateCertificateRequestreturns DER;pem.EncodeToMemorywith typeCERTIFICATE REQUESTwrites the usual PEM, andMarshalPKCS8PrivateKeythe key.
Gotchas
- Go does not copy the CommonName into the SANs: a template with only
CommonNamegives a CSR without any SAN (DNSNames=[]), and Go clients reject certificates like that withx509: certificate relies on legacy Common Name field. SignatureAlgorithmmay be left empty — Go picks ECDSA-SHA256 for a P-256 key — but setting it documents the choice and fails loudly if the key does not match.- The key file is written with mode
0o600;os.WriteFilewith0o644would leave the private key readable by every user on the machine. x509.ParseCertificateRequestplusCheckSignature()verifies a CSR you receive; the CA side should always do that before signing.