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
|
package tlstool
import (
"crypto/tls"
"crypto/x509"
"fmt"
"os"
)
func LoadCACert(caCertFile string) (*x509.CertPool, error) {
certPool, err := x509.SystemCertPool()
if err != nil {
return nil, fmt.Errorf("SystemCertPool: %w", err)
}
caCert, err := os.ReadFile(caCertFile) // nolint: gosec
if err != nil {
return nil, fmt.Errorf("CA certificate file: %w", err)
}
ok := certPool.AppendCertsFromPEM(caCert)
if !ok {
return nil, fmt.Errorf("AppendCertsFromPEM(%s) failed", caCertFile)
}
return certPool, nil
}
func DefaultClientTLSConfig() *tls.Config {
return &tls.Config{
CipherSuites: secureCipherSuites(),
MinVersion: tls.VersionTLS12,
}
}
func DefaultClientTLSConfigWithCACert(caCertFile string) (*tls.Config, error) {
tlsConfig := DefaultClientTLSConfig()
if caCertFile != "" {
certPool, err := LoadCACert(caCertFile)
if err != nil {
return nil, err
}
tlsConfig.RootCAs = certPool
}
return tlsConfig, nil
}
func DefaultClientTLSConfigWithCACertKeyPair(caCertFile, certFile, keyFile string) (*tls.Config, error) {
tlsConfig, err := DefaultClientTLSConfigWithCACert(caCertFile)
if err != nil {
return nil, err
}
switch {
case certFile != "" && keyFile != "":
cert, err := tls.LoadX509KeyPair(certFile, keyFile)
if err != nil {
return nil, err
}
tlsConfig.Certificates = []tls.Certificate{cert}
case certFile == "" && keyFile == "":
// nothing to do
default:
return nil, fmt.Errorf("both certificate (%s) and key (%s) files must be specified", certFile, keyFile)
}
return tlsConfig, nil
}
func DefaultServerTLSConfig(certFile, keyFile string) (*tls.Config, error) {
cert, err := tls.LoadX509KeyPair(certFile, keyFile)
if err != nil {
return nil, fmt.Errorf("loading certificate (%s) and key (%s) files: %w", certFile, keyFile, err)
}
return &tls.Config{
Certificates: []tls.Certificate{cert},
CipherSuites: secureCipherSuites(),
MinVersion: tls.VersionTLS12,
}, nil
}
// MaybeDefaultServerTLSConfig is like DefaultServerTLSConfig but returns (nil, nil) if certFile and keyFile are empty.
func MaybeDefaultServerTLSConfig(certFile, keyFile string) (*tls.Config, error) {
switch {
case certFile != "" && keyFile != "":
config, err := DefaultServerTLSConfig(certFile, keyFile)
if err != nil {
return nil, err
}
return config, nil
case certFile == "" && keyFile == "":
return nil, nil
default:
return nil, fmt.Errorf("both certificate file (%s) and key file (%s) must be either specified or not", certFile, keyFile)
}
}
// Generated by https://ssl-config.mozilla.org/#server=go&version=1.17&config=intermediate&guideline=5.6
// on 2021-09-05
// See also https://github.com/golang/go/blob/go1.17/src/crypto/tls/cipher_suites.go#L206-L300.
func secureCipherSuites() []uint16 {
return []uint16{
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
}
}
|