@@ -104,6 +104,7 @@ const (
104
104
)
105
105
106
106
// TLSCertificate returns the Certificate as tls.Certificate.
107
+ // Complete certificate chain (up to but not including root) is included for end-entity certificates.
107
108
// A key pair and certificate will be generated at first call of any Certificate functions.
108
109
// Error is not nil if generation fails.
109
110
func (c * Certificate ) TLSCertificate () (tls.Certificate , error ) {
@@ -149,6 +150,7 @@ func (c *Certificate) PrivateKey() (crypto.Signer, error) {
149
150
}
150
151
151
152
// PEM returns the Certificate as certificate and private key PEM buffers.
153
+ // Complete certificate chain (up to but not including root) is included for end-entity certificates.
152
154
// A key pair and certificate will be generated at first call of any Certificate functions.
153
155
// Error is not nil if generation fails.
154
156
func (c * Certificate ) PEM () (cert []byte , key []byte , err error ) {
@@ -157,38 +159,28 @@ func (c *Certificate) PEM() (cert []byte, key []byte, err error) {
157
159
return
158
160
}
159
161
160
- var buf bytes.Buffer
161
-
162
- err = pem .Encode (& buf , & pem.Block {
163
- Type : "CERTIFICATE" ,
164
- Bytes : c .GeneratedCert .Certificate [0 ],
165
- })
162
+ cert , err = encodeToPEMBlocks ("CERTIFICATE" , c .GeneratedCert .Certificate )
166
163
if err != nil {
167
164
return
168
165
}
169
- cert = append (cert , buf .Bytes ()... ) // Create copy of underlying buf.
170
-
171
- buf .Reset ()
172
166
173
167
k , err := x509 .MarshalPKCS8PrivateKey (c .GeneratedCert .PrivateKey )
174
168
if err != nil {
175
169
cert = nil
176
170
return
177
171
}
178
- err = pem .Encode (& buf , & pem.Block {
179
- Type : "PRIVATE KEY" ,
180
- Bytes : k ,
181
- })
172
+
173
+ key , err = encodeToPEMBlocks ("PRIVATE KEY" , [][]byte {k })
182
174
if err != nil {
183
175
cert = nil
184
176
return
185
177
}
186
- key = append (key , buf .Bytes ()... ) // Create copy of underlying buf.
187
178
188
179
return
189
180
}
190
181
191
182
// WritePEM writes the Certificate as certificate and private key PEM files.
183
+ // Complete certificate chain (up to but not including root) is included for end-entity certificates.
192
184
// A key pair and certificate will be generated at first call of any Certificate functions.
193
185
// Error is not nil if generation fails.
194
186
func (c * Certificate ) WritePEM (certFile , keyFile string ) error {
@@ -357,13 +349,25 @@ func (c *Certificate) Generate() error {
357
349
358
350
var issuerCert * x509.Certificate
359
351
var issuerKey crypto.Signer
352
+ var chain [][]byte
360
353
if c .Issuer != nil {
361
354
issuerCert , err = x509 .ParseCertificate (c .Issuer .GeneratedCert .Certificate [0 ])
362
355
if err != nil {
363
356
return nil
364
357
}
365
358
issuerKey = c .Issuer .GeneratedCert .PrivateKey .(crypto.Signer )
366
359
360
+ // Add certificate chain to end-entity certificates.
361
+ if ! * c .IsCA {
362
+ issuer := c .Issuer
363
+ for issuer != nil {
364
+ // Add issuer to chain unless it is root certificate.
365
+ if issuer .Issuer != nil {
366
+ chain = append (chain , issuer .GeneratedCert .Certificate [0 ])
367
+ }
368
+ issuer = issuer .Issuer
369
+ }
370
+ }
367
371
} else {
368
372
// create self-signed certificate
369
373
issuerCert = template
@@ -377,9 +381,26 @@ func (c *Certificate) Generate() error {
377
381
}
378
382
379
383
c .GeneratedCert = & tls.Certificate {
380
- Certificate : [][]byte {cert },
384
+ Certificate : append ( [][]byte {cert }, chain ... ) ,
381
385
PrivateKey : key ,
382
386
}
383
387
384
388
return nil
385
389
}
390
+
391
+ func encodeToPEMBlocks (blockType string , blocks [][]byte ) ([]byte , error ) {
392
+ var buf bytes.Buffer
393
+
394
+ for _ , b := range blocks {
395
+ err := pem .Encode (& buf , & pem.Block {
396
+ Type : blockType ,
397
+ Bytes : b ,
398
+ })
399
+ if err != nil {
400
+ return nil , err
401
+ }
402
+
403
+ }
404
+
405
+ return buf .Bytes (), nil
406
+ }
0 commit comments