@@ -51,12 +51,8 @@ func (m *mkcert) makeCert(hosts []string) {
5151 fatalIfErr (err , "failed to generate certificate key" )
5252 pub := priv .(crypto.Signer ).Public ()
5353
54- serialNumberLimit := new (big.Int ).Lsh (big .NewInt (1 ), 128 )
55- serialNumber , err := rand .Int (rand .Reader , serialNumberLimit )
56- fatalIfErr (err , "failed to generate serial number" )
57-
5854 tpl := & x509.Certificate {
59- SerialNumber : serialNumber ,
55+ SerialNumber : randomSerialNumber () ,
6056 Subject : pkix.Name {
6157 Organization : []string {"mkcert development certificate" },
6258 OrganizationalUnit : []string {userAndHostname },
@@ -100,7 +96,7 @@ func (m *mkcert) makeCert(hosts []string) {
10096
10197 err = ioutil .WriteFile (certFile , pem .EncodeToMemory (
10298 & pem.Block {Type : "CERTIFICATE" , Bytes : cert }), 0644 )
103- fatalIfErr (err , "failed to save certificate key " )
99+ fatalIfErr (err , "failed to save certificate" )
104100 } else {
105101 domainCert , _ := x509 .ParseCertificate (cert )
106102 pfxData , err := pkcs12 .Encode (rand .Reader , priv , domainCert , []* x509.Certificate {m .caCert }, "changeit" )
@@ -109,6 +105,17 @@ func (m *mkcert) makeCert(hosts []string) {
109105 fatalIfErr (err , "failed to save PKCS#12" )
110106 }
111107
108+ m .printHosts (hosts )
109+
110+ if ! m .pkcs12 {
111+ log .Printf ("\n The certificate is at \" %s\" and the key at \" %s\" ✅\n \n " , certFile , keyFile )
112+ } else {
113+ log .Printf ("\n The PKCS#12 bundle is at \" %s\" ✅\n " , p12File )
114+ log .Printf ("\n The legacy PKCS#12 encryption password is the often hardcoded default \" changeit\" ℹ️\n \n " )
115+ }
116+ }
117+
118+ func (m * mkcert ) printHosts (hosts []string ) {
112119 secondLvlWildcardRegexp := regexp .MustCompile (`(?i)^\*\.[0-9a-z_-]+$` )
113120 log .Printf ("\n Created a new certificate valid for the following names 📜" )
114121 for _ , h := range hosts {
@@ -124,13 +131,6 @@ func (m *mkcert) makeCert(hosts []string) {
124131 break
125132 }
126133 }
127-
128- if ! m .pkcs12 {
129- log .Printf ("\n The certificate is at \" %s\" and the key at \" %s\" ✅\n \n " , certFile , keyFile )
130- } else {
131- log .Printf ("\n The PKCS#12 bundle is at \" %s\" ✅\n " , p12File )
132- log .Printf ("\n The legacy PKCS#12 encryption password is the often hardcoded default \" changeit\" ℹ️\n \n " )
133- }
134134}
135135
136136func (m * mkcert ) generateKey (rootCA bool ) (crypto.PrivateKey , error ) {
@@ -166,6 +166,72 @@ func (m *mkcert) fileNames(hosts []string) (certFile, keyFile, p12File string) {
166166 return
167167}
168168
169+ func randomSerialNumber () * big.Int {
170+ serialNumberLimit := new (big.Int ).Lsh (big .NewInt (1 ), 128 )
171+ serialNumber , err := rand .Int (rand .Reader , serialNumberLimit )
172+ fatalIfErr (err , "failed to generate serial number" )
173+ return serialNumber
174+ }
175+
176+ func (m * mkcert ) makeCertFromCSR () {
177+ if m .caKey == nil {
178+ log .Fatalln ("ERROR: can't create new certificates because the CA key (rootCA-key.pem) is missing" )
179+ }
180+
181+ csrPEMBytes , err := ioutil .ReadFile (m .csrPath )
182+ fatalIfErr (err , "failed to read the CSR" )
183+ csrPEM , _ := pem .Decode (csrPEMBytes )
184+ if csrPEM == nil {
185+ log .Fatalln ("ERROR: failed to read the CSR: unexpected content" )
186+ }
187+ if csrPEM .Type != "CERTIFICATE REQUEST" {
188+ log .Fatalln ("ERROR: failed to read the CSR: expected CERTIFICATE REQUEST, got " + csrPEM .Type )
189+ }
190+ csr , err := x509 .ParseCertificateRequest (csrPEM .Bytes )
191+ fatalIfErr (err , "failed to parse the CSR" )
192+ fatalIfErr (csr .CheckSignature (), "invalid CSR signature" )
193+
194+ tpl := & x509.Certificate {
195+ SerialNumber : randomSerialNumber (),
196+ Subject : csr .Subject ,
197+ ExtraExtensions : csr .Extensions , // includes requested SANs
198+
199+ NotAfter : time .Now ().AddDate (10 , 0 , 0 ),
200+ NotBefore : time .Now (),
201+
202+ KeyUsage : x509 .KeyUsageKeyEncipherment | x509 .KeyUsageDigitalSignature ,
203+ ExtKeyUsage : []x509.ExtKeyUsage {x509 .ExtKeyUsageServerAuth },
204+ BasicConstraintsValid : true ,
205+
206+ // If the CSR does not request a SAN extension, fix it up for them as
207+ // the Common Name field does not work in modern browsers. Otherwise,
208+ // this will get overridden.
209+ DNSNames : []string {csr .Subject .CommonName },
210+ }
211+
212+ cert , err := x509 .CreateCertificate (rand .Reader , tpl , m .caCert , csr .PublicKey , m .caKey )
213+ fatalIfErr (err , "failed to generate certificate" )
214+
215+ var hosts []string
216+ hosts = append (hosts , csr .DNSNames ... )
217+ hosts = append (hosts , csr .EmailAddresses ... )
218+ for _ , ip := range csr .IPAddresses {
219+ hosts = append (hosts , ip .String ())
220+ }
221+ if len (hosts ) == 0 {
222+ hosts = []string {csr .Subject .CommonName }
223+ }
224+ certFile , _ , _ := m .fileNames (hosts )
225+
226+ err = ioutil .WriteFile (certFile , pem .EncodeToMemory (
227+ & pem.Block {Type : "CERTIFICATE" , Bytes : cert }), 0644 )
228+ fatalIfErr (err , "failed to save certificate" )
229+
230+ m .printHosts (hosts )
231+
232+ log .Printf ("\n The certificate is at \" %s\" ✅\n \n " , certFile )
233+ }
234+
169235// loadCA will load or create the CA at CAROOT.
170236func (m * mkcert ) loadCA () {
171237 if _ , err := os .Stat (filepath .Join (m .CAROOT , rootName )); os .IsNotExist (err ) {
@@ -202,10 +268,6 @@ func (m *mkcert) newCA() {
202268 fatalIfErr (err , "failed to generate the CA key" )
203269 pub := priv .(crypto.Signer ).Public ()
204270
205- serialNumberLimit := new (big.Int ).Lsh (big .NewInt (1 ), 128 )
206- serialNumber , err := rand .Int (rand .Reader , serialNumberLimit )
207- fatalIfErr (err , "failed to generate serial number" )
208-
209271 spkiASN1 , err := x509 .MarshalPKIXPublicKey (pub )
210272 fatalIfErr (err , "failed to encode public key" )
211273
@@ -219,7 +281,7 @@ func (m *mkcert) newCA() {
219281 skid := sha1 .Sum (spki .SubjectPublicKey .Bytes )
220282
221283 tpl := & x509.Certificate {
222- SerialNumber : serialNumber ,
284+ SerialNumber : randomSerialNumber () ,
223285 Subject : pkix.Name {
224286 Organization : []string {"mkcert development CA" },
225287 OrganizationalUnit : []string {userAndHostname },
0 commit comments