-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29
-
30
-
31
-
32
-
33
-
34
-
35
-
36
-
37
-
38
-
39
-
40
-
41
-
42
-
43
-
44
-
45
-
46
-
47
-
48
-
49
-
50
-
51
-
52
-
53
-
54
-
55
-
56
-
57
-
58
-
59
-
60
-
61
-
62
-
63
-
64
-
65
-
66
-
67
-
68
-
69
-
70
-
71
-
72
-
73
-
74
-
75
-
76
-
77
-
78
-
79
-
80
-
81
-
82
-
83
-
84
-
85
-
86
-
87
-
88
-
89
-
90
-
91
-
92
-
93
-
94
-
95
-
96
-
97
-
98
-
99
-
100
-
101
-
102
-
103
-
104
-
105
-
106
-
107
-
108
-
109
-
110
-
111
-
112
-
113
-
114
-
115
-
116
-
117
-
118
-
119
-
120
-
121
-
122
-
123
-
124
-
125
-
126
-
127
-
128
-
129
-
130
-
131
-
132
-
133
-
134
-
135
-
136
-
137
-
138
-
139
-
140
-
141
-
142
-
143
-
144
-
145
-
146
-
147
-
148
-
149
-
150
-
151
-
152
-
153
-
154
-
155
-
156
-
157
-
158
-
159
-
160
-
161
-
162
-
163
-
164
-
165
-
166
-
167
-
168
-
169
-
170
-
171
-
172
-
173
-
174
-
175
-
176
-
177
-
178
-
179
-
180
-
181
-
182
-
183
-
184
-
185
-
186
-
187
-
188
-
189
-
190
-
191
-
192
-
193
-
194
-
195
-
196
-
197
-
198
-
199
-
200
-
201
-
202
-
203
-
204
-
205
-
206
-
207
-
208
-
209
-
210
-
211
-
212
-
213
-
214
-
215
-
216
-
217
-
218
-
219
-
220
-
221
-
222
-
223
-
224
-
225
-
226
-
227
-
228
-
229
-
230
-
231
-
232
-
233
-
234
-
235
-
236
-
237
-
238
-
239
-
240
-
241
-
242
-
243
-
244
-
245
-
246
-
247
-
248
-
249
-
250
-
251
-
252
-
253
-
254
-
255
-
256
-
257
-
258
-
259
-
260
-
261
-
262
-
263
-
264
-
265
-
266
-
267
-
268
-
269
-
270
-
271
-
272
-
273
-
274
-
275
-
276
-
277
-
278
-
279
-
280
-
281
-
282
-
283
-
284
-
285
-
286
-
287
-
288
-
289
-
290
-
291
-
292
-
293
-
294
-
295
-
296
-
297
-
298
-
299
-
300
-
301
-
302
-
303
-
304
-
305
-
306
-
307
-
308
-
309
-
310
-
311
-
312
-
313
-
314
-
315
-
316
-
317
-
318
-
319
-
320
-
321
-
322
-
323
-
324
-
325
-
326
-
327
-
328
-
329
-
330
-
331
-
332
-
333
-
334
-
335
-
336
-
337
-
338
-
339
-
340
-
341
-
342
-
343
-
344
-
345
-
346
-
347
-
348
-
349
-
350
-
351
-
352
-
353
-
354
-
355
-
356
-
357
// Copyright 2015 Matthew Holt
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package certmagic
import (
"crypto"
"crypto/ecdsa"
"crypto/ed25519"
"crypto/elliptic"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/tls"
"crypto/x509"
"encoding/json"
"encoding/pem"
"fmt"
"hash/fnv"
"sort"
"strings"
"github.com/klauspost/cpuid/v2"
"go.uber.org/zap"
"golang.org/x/net/idna"
)
// encodePrivateKey marshals a EC or RSA private key into a PEM-encoded array of bytes.
func encodePrivateKey(key crypto.PrivateKey) ([]byte, error) {
var pemType string
var keyBytes []byte
switch key := key.(type) {
case *ecdsa.PrivateKey:
var err error
pemType = "EC"
keyBytes, err = x509.MarshalECPrivateKey(key)
if err != nil {
return nil, err
}
case *rsa.PrivateKey:
pemType = "RSA"
keyBytes = x509.MarshalPKCS1PrivateKey(key)
case ed25519.PrivateKey:
var err error
pemType = "ED25519"
keyBytes, err = x509.MarshalPKCS8PrivateKey(key)
if err != nil {
return nil, err
}
default:
return nil, fmt.Errorf("unsupported key type: %T", key)
}
pemKey := pem.Block{Type: pemType + " PRIVATE KEY", Bytes: keyBytes}
return pem.EncodeToMemory(&pemKey), nil
}
// decodePrivateKey loads a PEM-encoded ECC/RSA private key from an array of bytes.
// Borrowed from Go standard library, to handle various private key and PEM block types.
// https://github.com/golang/go/blob/693748e9fa385f1e2c3b91ca9acbb6c0ad2d133d/src/crypto/tls/tls.go#L291-L308
// https://github.com/golang/go/blob/693748e9fa385f1e2c3b91ca9acbb6c0ad2d133d/src/crypto/tls/tls.go#L238)
func decodePrivateKey(keyPEMBytes []byte) (crypto.Signer, error) {
keyBlockDER, _ := pem.Decode(keyPEMBytes)
if keyBlockDER.Type != "PRIVATE KEY" && !strings.HasSuffix(keyBlockDER.Type, " PRIVATE KEY") {
return nil, fmt.Errorf("unknown PEM header %q", keyBlockDER.Type)
}
if key, err := x509.ParsePKCS1PrivateKey(keyBlockDER.Bytes); err == nil {
return key, nil
}
if key, err := x509.ParsePKCS8PrivateKey(keyBlockDER.Bytes); err == nil {
switch key := key.(type) {
case *rsa.PrivateKey, *ecdsa.PrivateKey, ed25519.PrivateKey:
return key.(crypto.Signer), nil
default:
return nil, fmt.Errorf("found unknown private key type in PKCS#8 wrapping: %T", key)
}
}
if key, err := x509.ParseECPrivateKey(keyBlockDER.Bytes); err == nil {
return key, nil
}
return nil, fmt.Errorf("unknown private key type")
}
// parseCertsFromPEMBundle parses a certificate bundle from top to bottom and returns
// a slice of x509 certificates. This function will error if no certificates are found.
func parseCertsFromPEMBundle(bundle []byte) ([]*x509.Certificate, error) {
var certificates []*x509.Certificate
var certDERBlock *pem.Block
for {
certDERBlock, bundle = pem.Decode(bundle)
if certDERBlock == nil {
break
}
if certDERBlock.Type == "CERTIFICATE" {
cert, err := x509.ParseCertificate(certDERBlock.Bytes)
if err != nil {
return nil, err
}
certificates = append(certificates, cert)
}
}
if len(certificates) == 0 {
return nil, fmt.Errorf("no certificates found in bundle")
}
return certificates, nil
}
// fastHash hashes input using a hashing algorithm that
// is fast, and returns the hash as a hex-encoded string.
// Do not use this for cryptographic purposes.
func fastHash(input []byte) string {
h := fnv.New32a()
h.Write(input)
return fmt.Sprintf("%x", h.Sum32())
}
// saveCertResource saves the certificate resource to disk. This
// includes the certificate file itself, the private key, and the
// metadata file.
func (cfg *Config) saveCertResource(issuer Issuer, cert CertificateResource) error {
metaBytes, err := json.MarshalIndent(cert, "", "\t")
if err != nil {
return fmt.Errorf("encoding certificate metadata: %v", err)
}
issuerKey := issuer.IssuerKey()
certKey := cert.NamesKey()
all := []keyValue{
{
key: StorageKeys.SiteCert(issuerKey, certKey),
value: cert.CertificatePEM,
},
{
key: StorageKeys.SitePrivateKey(issuerKey, certKey),
value: cert.PrivateKeyPEM,
},
{
key: StorageKeys.SiteMeta(issuerKey, certKey),
value: metaBytes,
},
}
return storeTx(cfg.Storage, all)
}
// loadCertResourceAnyIssuer loads and returns the certificate resource from any
// of the configured issuers. If multiple are found (e.g. if there are 3 issuers
// configured, and all 3 have a resource matching certNamesKey), then the newest
// (latest NotBefore date) resource will be chosen.
func (cfg *Config) loadCertResourceAnyIssuer(certNamesKey string) (CertificateResource, error) {
// we can save some extra decoding steps if there's only one issuer, since
// we don't need to compare potentially multiple available resources to
// select the best one, when there's only one choice anyway
if len(cfg.Issuers) == 1 {
return cfg.loadCertResource(cfg.Issuers[0], certNamesKey)
}
type decodedCertResource struct {
CertificateResource
issuer Issuer
decoded *x509.Certificate
}
var certResources []decodedCertResource
var lastErr error
// load and decode all certificate resources found with the
// configured issuers so we can sort by newest
for _, issuer := range cfg.Issuers {
certRes, err := cfg.loadCertResource(issuer, certNamesKey)
if err != nil {
if _, ok := err.(ErrNotExist); ok {
// not a problem, but we need to remember the error
// in case we end up not finding any cert resources
// since we'll need an error to return in that case
lastErr = err
continue
}
return CertificateResource{}, err
}
certs, err := parseCertsFromPEMBundle(certRes.CertificatePEM)
if err != nil {
return CertificateResource{}, err
}
certResources = append(certResources, decodedCertResource{
CertificateResource: certRes,
issuer: issuer,
decoded: certs[0],
})
}
if len(certResources) == 0 {
if lastErr == nil {
lastErr = fmt.Errorf("no certificate resources found") // just in case; e.g. no Issuers configured
}
return CertificateResource{}, lastErr
}
// sort by date so the most recently issued comes first
sort.Slice(certResources, func(i, j int) bool {
return certResources[j].decoded.NotBefore.Before(certResources[i].decoded.NotBefore)
})
if cfg.Logger != nil {
cfg.Logger.Debug("loading managed certificate",
zap.String("domain", certNamesKey),
zap.Time("expiration", certResources[0].decoded.NotAfter),
zap.String("issuer_key", certResources[0].issuer.IssuerKey()),
zap.Any("storage", cfg.Storage),
)
}
return certResources[0].CertificateResource, nil
}
// loadCertResource loads a certificate resource from the given issuer's storage location.
func (cfg *Config) loadCertResource(issuer Issuer, certNamesKey string) (CertificateResource, error) {
certRes := CertificateResource{issuerKey: issuer.IssuerKey()}
normalizedName, err := idna.ToASCII(certNamesKey)
if err != nil {
return CertificateResource{}, fmt.Errorf("converting '%s' to ASCII: %v", certNamesKey, err)
}
certBytes, err := cfg.Storage.Load(StorageKeys.SiteCert(certRes.issuerKey, normalizedName))
if err != nil {
return CertificateResource{}, err
}
certRes.CertificatePEM = certBytes
keyBytes, err := cfg.Storage.Load(StorageKeys.SitePrivateKey(certRes.issuerKey, normalizedName))
if err != nil {
return CertificateResource{}, err
}
certRes.PrivateKeyPEM = keyBytes
metaBytes, err := cfg.Storage.Load(StorageKeys.SiteMeta(certRes.issuerKey, normalizedName))
if err != nil {
return CertificateResource{}, err
}
err = json.Unmarshal(metaBytes, &certRes)
if err != nil {
return CertificateResource{}, fmt.Errorf("decoding certificate metadata: %v", err)
}
return certRes, nil
}
// hashCertificateChain computes the unique hash of certChain,
// which is the chain of DER-encoded bytes. It returns the
// hex encoding of the hash.
func hashCertificateChain(certChain [][]byte) string {
h := sha256.New()
for _, certInChain := range certChain {
h.Write(certInChain)
}
return fmt.Sprintf("%x", h.Sum(nil))
}
func namesFromCSR(csr *x509.CertificateRequest) []string {
var nameSet []string
nameSet = append(nameSet, csr.DNSNames...)
nameSet = append(nameSet, csr.EmailAddresses...)
for _, v := range csr.IPAddresses {
nameSet = append(nameSet, v.String())
}
for _, v := range csr.URIs {
nameSet = append(nameSet, v.String())
}
return nameSet
}
// preferredDefaultCipherSuites returns an appropriate
// cipher suite to use depending on hardware support
// for AES-NI.
//
// See https://github.com/mholt/caddy/issues/1674
func preferredDefaultCipherSuites() []uint16 {
if cpuid.CPU.Supports(cpuid.AESNI) {
return defaultCiphersPreferAES
}
return defaultCiphersPreferChaCha
}
var (
defaultCiphersPreferAES = []uint16{
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
}
defaultCiphersPreferChaCha = []uint16{
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
}
)
// StandardKeyGenerator is the standard, in-memory key source
// that uses crypto/rand.
type StandardKeyGenerator struct {
// The type of keys to generate.
KeyType KeyType
}
// GenerateKey generates a new private key according to kg.KeyType.
func (kg StandardKeyGenerator) GenerateKey() (crypto.PrivateKey, error) {
switch kg.KeyType {
case ED25519:
_, priv, err := ed25519.GenerateKey(rand.Reader)
return priv, err
case "", P256:
return ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
case P384:
return ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
case RSA2048:
return rsa.GenerateKey(rand.Reader, 2048)
case RSA4096:
return rsa.GenerateKey(rand.Reader, 4096)
case RSA8192:
return rsa.GenerateKey(rand.Reader, 8192)
}
return nil, fmt.Errorf("unrecognized or unsupported key type: %s", kg.KeyType)
}
// DefaultKeyGenerator is the default key source.
var DefaultKeyGenerator = StandardKeyGenerator{KeyType: P256}
// KeyType enumerates the known/supported key types.
type KeyType string
// Constants for all key types we support.
const (
ED25519 = KeyType("ed25519")
P256 = KeyType("p256")
P384 = KeyType("p384")
RSA2048 = KeyType("rsa2048")
RSA4096 = KeyType("rsa4096")
RSA8192 = KeyType("rsa8192")
)