package transport import ( "crypto/rand" "crypto/rsa" "crypto/tls" "crypto/x509" "encoding/pem" "io/ioutil" "math/big" ) /* Example for self-signed certificates by openssl: Self CA: openssl genrsa -out ca.key 2048 openssl req -x509 -new -nodes -key ca.key -subj "/CN=example.ca.com" -days 5000 -out ca.crt Server: openssl genrsa -out server.key 2048 openssl req -new -key server.key -subj "/CN=example.server.com" -out server.csr openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 5000 Client: openssl genrsa -out client.key 2048 openssl req -new -key client.key -subj "/CN=example.client.com" -out client.csr openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 5000 */ func newCustomTLSKeyPair(certfile, keyfile string) (*tls.Certificate, error) { tlsCert, err := tls.LoadX509KeyPair(certfile, keyfile) if err != nil { return nil, err } return &tlsCert, nil } func newRandomTLSKeyPair() *tls.Certificate { key, err := rsa.GenerateKey(rand.Reader, 1024) if err != nil { panic(err) } template := x509.Certificate{SerialNumber: big.NewInt(1)} certDER, err := x509.CreateCertificate( rand.Reader, &template, &template, &key.PublicKey, key) if err != nil { panic(err) } keyPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)}) certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDER}) tlsCert, err := tls.X509KeyPair(certPEM, keyPEM) if err != nil { panic(err) } return &tlsCert } // Only supprt one ca file to add func newCertPool(caPath string) (*x509.CertPool, error) { pool := x509.NewCertPool() caCrt, err := ioutil.ReadFile(caPath) if err != nil { return nil, err } pool.AppendCertsFromPEM(caCrt) return pool, nil } func NewServerTLSConfig(certPath, keyPath, caPath string) (*tls.Config, error) { var base = &tls.Config{} if certPath == "" || keyPath == "" { // server will generate tls conf by itself cert := newRandomTLSKeyPair() base.Certificates = []tls.Certificate{*cert} } else { cert, err := newCustomTLSKeyPair(certPath, keyPath) if err != nil { return nil, err } base.Certificates = []tls.Certificate{*cert} } if caPath != "" { pool, err := newCertPool(caPath) if err != nil { return nil, err } base.ClientAuth = tls.RequireAndVerifyClientCert base.ClientCAs = pool } return base, nil } func NewClientTLSConfig(certPath, keyPath, caPath, servearName string) (*tls.Config, error) { var base = &tls.Config{} if certPath == "" || keyPath == "" { // client will not generate tls conf by itself } else { cert, err := newCustomTLSKeyPair(certPath, keyPath) if err != nil { return nil, err } base.Certificates = []tls.Certificate{*cert} } if caPath != "" { pool, err := newCertPool(caPath) if err != nil { return nil, err } base.RootCAs = pool base.ServerName = servearName base.InsecureSkipVerify = false } else { base.InsecureSkipVerify = true } return base, nil }