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 }