nanomsg.org/go/mangos/v2@v2.0.9-0.20200203084354-8a092611e461/internal/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 "testing" 28 "time" 29 ) 30 31 // KeyPair is a single public key pair 32 type KeyPair struct { 33 key *rsa.PrivateKey 34 cert *x509.Certificate 35 pair tls.Certificate 36 certDER []byte 37 38 KeyPEM []byte // PEM content for private key 39 CertPEM []byte // PEM content for certificate 40 } 41 42 // Keys is a set of the Root, Server, and Client keys for a test config. 43 type Keys struct { 44 Root KeyPair // Root CA key pair 45 Server KeyPair // Server key pair 46 Client KeyPair // Client key pair 47 } 48 49 func (k *KeyPair) genKey(bits int) (err error) { 50 if k.key, err = rsa.GenerateKey(rand.Reader, bits); err != nil { 51 return 52 } 53 k.KeyPEM = pem.EncodeToMemory(&pem.Block{ 54 Type: "RSA PRIVATE KEY", 55 Bytes: x509.MarshalPKCS1PrivateKey(k.key), 56 }) 57 return 58 } 59 60 func (k *KeyPair) genCert(tmpl *x509.Certificate, parent *KeyPair) (err error) { 61 k.cert = tmpl // for self-signed, we pass ourself as parent, this makes it work 62 k.certDER, err = x509.CreateCertificate(rand.Reader, tmpl, parent.cert, &k.key.PublicKey, parent.key) 63 if err != nil { 64 return 65 } 66 if k.cert, err = x509.ParseCertificate(k.certDER); err != nil { 67 return 68 } 69 k.CertPEM = pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: k.certDER}) 70 71 k.pair, err = tls.X509KeyPair(k.CertPEM, k.KeyPEM) 72 if err != nil { 73 return 74 } 75 return 76 } 77 78 func newKeys() (k *Keys, err error) { 79 k = &Keys{} 80 if err = k.Root.genKey(2048); err != nil { 81 return nil, err 82 } 83 if err = k.Server.genKey(1024); err != nil { 84 return nil, err 85 } 86 if err = k.Client.genKey(1024); err != nil { 87 return nil, err 88 } 89 90 if err = k.Root.genCert(rootTmpl, &k.Root); err != nil { 91 return nil, err 92 } 93 if err = k.Server.genCert(serverTmpl, &k.Root); err != nil { 94 return nil, err 95 } 96 if err = k.Client.genCert(clientTmpl, &k.Root); err != nil { 97 return nil, err 98 } 99 100 return k, nil 101 } 102 103 var rootTmpl = &x509.Certificate{ 104 SerialNumber: big.NewInt(1), 105 106 Issuer: pkix.Name{ 107 CommonName: "issuer.mangos.example.com", 108 Organization: []string{"Mangos Issuer Org"}, 109 }, 110 Subject: pkix.Name{ 111 CommonName: "Root.mangos.example.com", 112 Organization: []string{"Mangos Root Org"}, 113 }, 114 NotBefore: time.Unix(1000, 0), 115 NotAfter: time.Now().Add(time.Hour), 116 IsCA: true, 117 BasicConstraintsValid: true, 118 OCSPServer: []string{"ocsp.mangos.example.com"}, 119 DNSNames: []string{"Root.mangos.example.com"}, 120 IPAddresses: []net.IP{net.ParseIP("127.0.0.1")}, 121 SignatureAlgorithm: x509.SHA1WithRSA, 122 KeyUsage: x509.KeyUsageCertSign, 123 ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, 124 } 125 126 var serverTmpl = &x509.Certificate{ 127 SerialNumber: big.NewInt(2), 128 129 Issuer: pkix.Name{ 130 CommonName: "issuer.mangos.example.com", 131 Organization: []string{"Mangos Issuer Org"}, 132 }, 133 Subject: pkix.Name{ 134 CommonName: "Server.mangos.example.com", 135 Organization: []string{"Mangos Server Org"}, 136 }, 137 NotBefore: time.Unix(1000, 0), 138 NotAfter: time.Now().Add(time.Hour), 139 IsCA: false, 140 OCSPServer: []string{"ocsp.mangos.example.com"}, 141 DNSNames: []string{"Server.mangos.example.com"}, 142 IPAddresses: []net.IP{net.ParseIP("127.0.0.1")}, 143 SignatureAlgorithm: x509.SHA1WithRSA, 144 KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, 145 ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, 146 } 147 148 var clientTmpl = &x509.Certificate{ 149 SerialNumber: big.NewInt(3), 150 151 Issuer: pkix.Name{ 152 CommonName: "issuer.mangos.example.com", 153 Organization: []string{"Mangos Issuer Org"}, 154 }, 155 Subject: pkix.Name{ 156 CommonName: "Client.mangos.example.com", 157 Organization: []string{"Mangos Client Org"}, 158 }, 159 NotBefore: time.Unix(1000, 0), 160 NotAfter: time.Now().Add(time.Hour), 161 IsCA: false, 162 OCSPServer: []string{"ocsp.mangos.example.com"}, 163 DNSNames: []string{"Client.mangos.example.com"}, 164 IPAddresses: []net.IP{net.ParseIP("127.0.0.1")}, 165 SignatureAlgorithm: x509.SHA1WithRSA, 166 KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, 167 ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, 168 } 169 170 // NewTLSConfig creates a suitable TLS configuration, using 171 // either a Server or Client. 172 func NewTLSConfig() (*tls.Config, *tls.Config, *Keys, error) { 173 srvCfg := &tls.Config{} 174 cliCfg := &tls.Config{} 175 176 keys, err := newKeys() 177 if err != nil { 178 return nil, nil, nil, err 179 } 180 181 // Server side config. 182 srvCfg.Certificates = append(srvCfg.Certificates, keys.Server.pair) 183 184 // Client side config. 185 cliCfg.Certificates = append(cliCfg.Certificates, keys.Client.pair) 186 187 // Now configure the things the Client needs to know -- the self-signed 188 // Root CA, and also the Server's identity. 189 cliCfg.ServerName = "127.0.0.1" 190 cliCfg.RootCAs = x509.NewCertPool() 191 cliCfg.RootCAs.AddCert(keys.Root.cert) 192 return srvCfg, cliCfg, keys, nil 193 } 194 195 var lock sync.Mutex 196 var clientConfig *tls.Config 197 var serverConfig *tls.Config 198 var keys *Keys 199 200 // GetTLSConfig is like NewTLSConfig, but it caches to avoid regenerating 201 // key material pointlessly. 202 func GetTLSConfig(t *testing.T, server bool) *tls.Config { 203 var err error 204 lock.Lock() 205 defer lock.Unlock() 206 207 if serverConfig == nil || clientConfig == nil || keys == nil { 208 serverConfig, clientConfig, keys, err = NewTLSConfig() 209 MustSucceed(t, err) 210 } 211 if server { 212 return serverConfig 213 } 214 return clientConfig 215 } 216 217 // GetTLSConfigKeys is like NewTLSConfig, but it caches to avoid regenerating 218 // key material pointlessly. It also returns the Keys. 219 func GetTLSConfigKeys(t *testing.T) (*tls.Config, *tls.Config, *Keys) { 220 var err error 221 lock.Lock() 222 defer lock.Unlock() 223 224 if serverConfig == nil || clientConfig == nil || keys == nil { 225 serverConfig, clientConfig, keys, err = NewTLSConfig() 226 MustSucceed(t, err) 227 } 228 return serverConfig, clientConfig, keys 229 }