You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

crypto.go 11KB

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