nanomsg.org/go/mangos/v2@v2.0.9-0.20200203084354-8a092611e461/test/certs.go (about)

     1  // Copyright 2018 The Mangos Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use 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 O R 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  
    15  package test
    16  
    17  import (
    18  	"crypto/rand"
    19  	"crypto/rsa"
    20  	"crypto/tls"
    21  	"crypto/x509"
    22  	"crypto/x509/pkix"
    23  	"encoding/pem"
    24  	"math/big"
    25  	"net"
    26  	"sync"
    27  	"time"
    28  )
    29  
    30  type key struct {
    31  	key    *rsa.PrivateKey
    32  	keyPEM []byte
    33  
    34  	cert    *x509.Certificate
    35  	certDER []byte
    36  	certPEM []byte
    37  
    38  	pair tls.Certificate
    39  }
    40  
    41  type keys struct {
    42  	root   key
    43  	server key
    44  	client key
    45  }
    46  
    47  func (k *key) genKey(bits int) (err error) {
    48  	if k.key, err = rsa.GenerateKey(rand.Reader, bits); err != nil {
    49  		return
    50  	}
    51  	k.keyPEM = pem.EncodeToMemory(&pem.Block{
    52  		Type:  "RSA PRIVATE KEY",
    53  		Bytes: x509.MarshalPKCS1PrivateKey(k.key),
    54  	})
    55  	return
    56  }
    57  
    58  func (k *key) genCert(tmpl *x509.Certificate, parent *key) (err error) {
    59  	k.cert = tmpl // for self-signed, we pass ourself as parent, this makes it work
    60  	k.certDER, err = x509.CreateCertificate(rand.Reader, tmpl, parent.cert, &k.key.PublicKey, parent.key)
    61  	if err != nil {
    62  		return
    63  	}
    64  	if k.cert, err = x509.ParseCertificate(k.certDER); err != nil {
    65  		return
    66  	}
    67  	k.certPEM = pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: k.certDER})
    68  
    69  	k.pair, err = tls.X509KeyPair(k.certPEM, k.keyPEM)
    70  	if err != nil {
    71  		return
    72  	}
    73  	return
    74  }
    75  
    76  func newKeys() (k *keys, err error) {
    77  	k = &keys{}
    78  	if err = k.root.genKey(2048); err != nil {
    79  		return nil, err
    80  	}
    81  	if err = k.server.genKey(1024); err != nil {
    82  		return nil, err
    83  	}
    84  	if err = k.client.genKey(1024); err != nil {
    85  		return nil, err
    86  	}
    87  
    88  	if err = k.root.genCert(rootTmpl, &k.root); err != nil {
    89  		return nil, err
    90  	}
    91  	if err = k.server.genCert(serverTmpl, &k.root); err != nil {
    92  		return nil, err
    93  	}
    94  	if err = k.client.genCert(clientTmpl, &k.root); err != nil {
    95  		return nil, err
    96  	}
    97  	return k, nil
    98  }
    99  
   100  var rootTmpl = &x509.Certificate{
   101  	SerialNumber: big.NewInt(1),
   102  
   103  	Issuer: pkix.Name{
   104  		CommonName:   "issuer.mangos.example.com",
   105  		Organization: []string{"Mangos Issuer Org"},
   106  	},
   107  	Subject: pkix.Name{
   108  		CommonName:   "root.mangos.example.com",
   109  		Organization: []string{"Mangos Root Org"},
   110  	},
   111  	NotBefore:             time.Unix(1000, 0),
   112  	NotAfter:              time.Now().Add(time.Hour),
   113  	IsCA:                  true,
   114  	BasicConstraintsValid: true,
   115  	OCSPServer:            []string{"ocsp.mangos.example.com"},
   116  	DNSNames:              []string{"root.mangos.example.com"},
   117  	IPAddresses:           []net.IP{net.ParseIP("127.0.0.1")},
   118  	SignatureAlgorithm:    x509.SHA1WithRSA,
   119  	KeyUsage:              x509.KeyUsageCertSign,
   120  	ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
   121  }
   122  
   123  var serverTmpl = &x509.Certificate{
   124  	SerialNumber: big.NewInt(2),
   125  
   126  	Issuer: pkix.Name{
   127  		CommonName:   "issuer.mangos.example.com",
   128  		Organization: []string{"Mangos Issuer Org"},
   129  	},
   130  	Subject: pkix.Name{
   131  		CommonName:   "server.mangos.example.com",
   132  		Organization: []string{"Mangos Server Org"},
   133  	},
   134  	NotBefore:          time.Unix(1000, 0),
   135  	NotAfter:           time.Now().Add(time.Hour),
   136  	IsCA:               false,
   137  	OCSPServer:         []string{"ocsp.mangos.example.com"},
   138  	DNSNames:           []string{"server.mangos.example.com"},
   139  	IPAddresses:        []net.IP{net.ParseIP("127.0.0.1")},
   140  	SignatureAlgorithm: x509.SHA1WithRSA,
   141  	KeyUsage:           x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
   142  	ExtKeyUsage:        []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
   143  }
   144  
   145  var clientTmpl = &x509.Certificate{
   146  	SerialNumber: big.NewInt(3),
   147  
   148  	Issuer: pkix.Name{
   149  		CommonName:   "issuer.mangos.example.com",
   150  		Organization: []string{"Mangos Issuer Org"},
   151  	},
   152  	Subject: pkix.Name{
   153  		CommonName:   "client.mangos.example.com",
   154  		Organization: []string{"Mangos Client Org"},
   155  	},
   156  	NotBefore:          time.Unix(1000, 0),
   157  	NotAfter:           time.Now().Add(time.Hour),
   158  	IsCA:               false,
   159  	OCSPServer:         []string{"ocsp.mangos.example.com"},
   160  	DNSNames:           []string{"client.mangos.example.com"},
   161  	IPAddresses:        []net.IP{net.ParseIP("127.0.0.1")},
   162  	SignatureAlgorithm: x509.SHA1WithRSA,
   163  	KeyUsage:           x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
   164  	ExtKeyUsage:        []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
   165  }
   166  
   167  // NewTLSConfig creates a suitable TLS configuration, using
   168  // either a server or client.  A self-signed CA Cert is included.
   169  func NewTLSConfig(server bool) (*tls.Config, error) {
   170  	cfg := &tls.Config{}
   171  
   172  	keys, err := newKeys()
   173  	if err != nil {
   174  		return nil, err
   175  	}
   176  
   177  	if server {
   178  		cfg.Certificates = append(cfg.Certificates, keys.server.pair)
   179  	} else {
   180  		cfg.Certificates = append(cfg.Certificates, keys.client.pair)
   181  	}
   182  	cfg.InsecureSkipVerify = true
   183  	return cfg, nil
   184  }
   185  
   186  var lock sync.Mutex
   187  var clientConfig *tls.Config
   188  var serverConfig *tls.Config
   189  
   190  // GetTLSConfig is like NewTLSConfig, but it caches to avoid regenerating
   191  // key material pointlessly.
   192  func GetTLSConfig(server bool) (*tls.Config, error) {
   193  	var err error
   194  	var cfg *tls.Config
   195  	lock.Lock()
   196  	if server {
   197  		if cfg = serverConfig; cfg == nil {
   198  			cfg, err = NewTLSConfig(true)
   199  			serverConfig = cfg
   200  		}
   201  	} else {
   202  		if cfg = clientConfig; cfg == nil {
   203  			cfg, err = NewTLSConfig(false)
   204  			clientConfig = cfg
   205  		}
   206  	}
   207  	lock.Unlock()
   208  	return cfg, err
   209  }