|
@@ -0,0 +1,136 @@
|
|
|
+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
|
|
|
+}
|