15
15
// code is based on the snippet https://gist.github.com/shaneutt/5e1995295cff6721c89a71d13a71c251
16
16
// with a permissive (Public Domain) License.
17
17
18
+ // TODO(dmitris) - refactor to move the code generating certificates and writing to files
19
+ // to a separate function.
20
+
18
21
package main
19
22
20
23
import (
@@ -23,6 +26,7 @@ import (
23
26
"crypto/x509"
24
27
"crypto/x509/pkix"
25
28
"encoding/pem"
29
+ "flag"
26
30
"log"
27
31
"math/big"
28
32
"net"
@@ -31,16 +35,21 @@ import (
31
35
)
32
36
33
37
func main () {
38
+ var genIntermediate = flag .Bool ("intermediate" , false , "generate intermediate CA" )
39
+ var outputSuffix = flag .String ("output-suffix" , "" , "suffix to append to generated files before the extension" )
40
+ flag .Parse ()
41
+
34
42
// set up our CA certificate
35
43
ca := & x509.Certificate {
36
44
SerialNumber : big .NewInt (2019 ),
37
45
Subject : pkix.Name {
38
- Organization : []string {"CA Company, INC." },
39
- Country : []string {"US" },
40
- Province : []string {"" },
41
- Locality : []string {"San Francisco" },
42
- StreetAddress : []string {"Golden Gate Bridge" },
43
- PostalCode : []string {"94016" },
46
+ Organization : []string {"CA Company, INC." },
47
+ OrganizationalUnit : []string {"CA Root Team" },
48
+ Country : []string {"US" },
49
+ Province : []string {"" },
50
+ Locality : []string {"San Francisco" },
51
+ StreetAddress : []string {"Golden Gate Bridge" },
52
+ PostalCode : []string {"94016" },
44
53
},
45
54
NotBefore : time .Now (),
46
55
NotAfter : time .Now ().AddDate (10 , 0 , 0 ),
@@ -64,19 +73,20 @@ func main() {
64
73
}
65
74
66
75
// pem encode
67
- caCertFile , err := os .OpenFile ("cacert.pem" , os .O_RDWR | os .O_CREATE | os .O_TRUNC , 0644 )
76
+ fname := "ca-root" + * outputSuffix + ".pem"
77
+ caCertFile , err := os .OpenFile (fname , os .O_RDWR | os .O_CREATE | os .O_TRUNC , 0644 )
68
78
if err != nil {
69
- log .Fatalf ("unable to write to cacert.pem : %v" , err )
79
+ log .Fatalf ("unable to write to %s : %v" , fname , err )
70
80
}
71
81
err = pem .Encode (caCertFile , & pem.Block {
72
82
Type : "CERTIFICATE" ,
73
83
Bytes : caBytes ,
74
84
})
75
85
if err != nil {
76
- log .Fatalf ("unable to write to cacert.pem : %v" , err )
86
+ log .Fatalf ("unable to write to %s : %v" , fname , err )
77
87
}
78
-
79
- caPrivKeyFile , err := os .OpenFile ("ca-key.pem" , os .O_RDWR | os .O_CREATE | os .O_TRUNC , 0400 )
88
+ fname = "ca-key" + * outputSuffix + ".pem"
89
+ caPrivKeyFile , err := os .OpenFile (fname , os .O_RDWR | os .O_CREATE | os .O_TRUNC , 0400 )
80
90
if err != nil {
81
91
log .Fatal (err )
82
92
}
@@ -86,19 +96,82 @@ func main() {
86
96
Bytes : x509 .MarshalPKCS1PrivateKey (caPrivKey ),
87
97
})
88
98
if err != nil {
89
- log .Fatalf ("unable to create to ca-key.pem : %v" , err ) //nolint:gocritic
99
+ log .Fatalf ("unable to create to %s : %v" , fname , err ) //nolint:gocritic
90
100
}
91
101
102
+ // generate intermediate CA if requested
103
+ var caIntermediate * x509.Certificate
104
+ var caIntermediatePrivKey * rsa.PrivateKey
105
+ if * genIntermediate {
106
+ caIntermediate = & x509.Certificate {
107
+ SerialNumber : big .NewInt (2019 ),
108
+ Subject : pkix.Name {
109
+ Organization : []string {"CA Company, INC." },
110
+ OrganizationalUnit : []string {"CA Intermediate Team" },
111
+ Country : []string {"US" },
112
+ Province : []string {"" },
113
+ Locality : []string {"San Francisco" },
114
+ StreetAddress : []string {"Golden Gate Bridge" },
115
+ PostalCode : []string {"94016" },
116
+ },
117
+ NotBefore : time .Now (),
118
+ NotAfter : time .Now ().AddDate (10 , 0 , 0 ),
119
+ IsCA : true ,
120
+ ExtKeyUsage : []x509.ExtKeyUsage {x509 .ExtKeyUsageCodeSigning /*, x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth */ },
121
+ KeyUsage : x509 .KeyUsageDigitalSignature | x509 .KeyUsageCertSign ,
122
+ BasicConstraintsValid : true ,
123
+ EmailAddresses : []string {"ca@example.com" },
124
+ }
125
+ // create our private and public key
126
+ caIntermediatePrivKey , err = rsa .GenerateKey (rand .Reader , 4096 )
127
+ if err != nil {
128
+ log .Fatal (err )
129
+ }
130
+
131
+ // create the Intermediate CA
132
+ caIntermediateBytes , err := x509 .CreateCertificate (rand .Reader , caIntermediate , ca , & caIntermediatePrivKey .PublicKey , caPrivKey )
133
+ if err != nil {
134
+ log .Fatal (err )
135
+ }
136
+
137
+ // pem encode
138
+ fname = "ca-intermediate" + * outputSuffix + ".pem"
139
+ caIntermediateCertFile , err := os .OpenFile (fname , os .O_RDWR | os .O_CREATE | os .O_TRUNC , 0644 )
140
+ if err != nil {
141
+ log .Fatalf ("unable to write to %s: %v" , fname , err )
142
+ }
143
+ err = pem .Encode (caIntermediateCertFile , & pem.Block {
144
+ Type : "CERTIFICATE" ,
145
+ Bytes : caIntermediateBytes ,
146
+ })
147
+ if err != nil {
148
+ log .Fatalf ("unable to write to %s: %v" , fname , err )
149
+ }
150
+ fname = "ca-intermediate-key" + * outputSuffix + ".pem"
151
+ caIntermediatePrivKeyFile , err := os .OpenFile (fname , os .O_RDWR | os .O_CREATE | os .O_TRUNC , 0400 )
152
+ if err != nil {
153
+ log .Fatal (err )
154
+ }
155
+ defer caIntermediatePrivKeyFile .Close ()
156
+ err = pem .Encode (caIntermediatePrivKeyFile , & pem.Block {
157
+ Type : "RSA PRIVATE KEY" ,
158
+ Bytes : x509 .MarshalPKCS1PrivateKey (caIntermediatePrivKey ),
159
+ })
160
+ if err != nil {
161
+ log .Fatalf ("unable to create to %s: %v" , fname , err ) //nolint:gocritic
162
+ }
163
+ }
92
164
// set up our server certificate
93
165
cert := & x509.Certificate {
94
166
SerialNumber : big .NewInt (2019 ),
95
167
Subject : pkix.Name {
96
- Organization : []string {"Company, INC." },
97
- Country : []string {"US" },
98
- Province : []string {"" },
99
- Locality : []string {"San Francisco" },
100
- StreetAddress : []string {"Golden Gate Bridge" },
101
- PostalCode : []string {"94016" },
168
+ Organization : []string {"End User" },
169
+ OrganizationalUnit : []string {"End Node Team" },
170
+ Country : []string {"US" },
171
+ Province : []string {"" },
172
+ Locality : []string {"San Francisco" },
173
+ StreetAddress : []string {"Golden Gate Bridge" },
174
+ PostalCode : []string {"94016" },
102
175
},
103
176
IPAddresses : []net.IP {net .IPv4 (127 , 0 , 0 , 1 ), net .IPv6loopback },
104
177
NotBefore : time .Now (),
@@ -115,12 +188,18 @@ func main() {
115
188
log .Fatal (err )
116
189
}
117
190
118
- certBytes , err := x509 .CreateCertificate (rand .Reader , cert , ca , & certPrivKey .PublicKey , caPrivKey )
191
+ var certBytes []byte
192
+ if ! * genIntermediate {
193
+ certBytes , err = x509 .CreateCertificate (rand .Reader , cert , ca , & certPrivKey .PublicKey , caPrivKey )
194
+ } else {
195
+ certBytes , err = x509 .CreateCertificate (rand .Reader , cert , caIntermediate , & caIntermediatePrivKey .PublicKey , caIntermediatePrivKey )
196
+ }
119
197
if err != nil {
120
198
log .Fatal (err )
121
199
}
122
200
123
- certFile , err := os .OpenFile ("cert.pem" , os .O_RDWR | os .O_CREATE | os .O_TRUNC , 0644 )
201
+ fname = "cert" + * outputSuffix + ".pem"
202
+ certFile , err := os .OpenFile (fname , os .O_RDWR | os .O_CREATE | os .O_TRUNC , 0644 )
124
203
if err != nil {
125
204
log .Fatal (err )
126
205
}
@@ -133,7 +212,8 @@ func main() {
133
212
log .Fatalf ("failed to encode cert: %v" , err )
134
213
}
135
214
136
- keyFile , err := os .OpenFile ("key.pem" , os .O_RDWR | os .O_CREATE | os .O_TRUNC , 0400 )
215
+ fname = "key" + * outputSuffix + ".pem"
216
+ keyFile , err := os .OpenFile (fname , os .O_RDWR | os .O_CREATE | os .O_TRUNC , 0400 )
137
217
if err != nil {
138
218
log .Fatal (err )
139
219
}
@@ -143,6 +223,6 @@ func main() {
143
223
Bytes : x509 .MarshalPKCS1PrivateKey (certPrivKey ),
144
224
})
145
225
if err != nil {
146
- log .Fatalf ("failed to encode private key: %v" , err )
226
+ log .Fatalf ("failed to encode private key to %s : %v" , fname , err )
147
227
}
148
228
}
0 commit comments