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