【发布时间】:2021-02-05 01:50:35
【问题描述】:
我在网上找到了这个代码,它动态生成 TLS 证书和密钥并注册它,当我运行它时,我也能够成功连接。
package main
import (
"bytes"
"crypto/rand"
"crypto/rsa"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"fmt"
"io/ioutil"
"math/big"
"net"
"net/http"
"net/http/httptest"
"strings"
"time"
)
func main() {
// get our ca and server certificate
serverTLSConf, clientTLSConf, err := certsetup()
if err != nil {
panic(err)
}
// set up the httptest.Server using our certificate signed by our CA
server := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "success!")
}))
server.TLS = serverTLSConf
server.StartTLS()
defer server.Close()
// communicate with the server using an http.Client configured to trust our CA
transport := &http.Transport{
TLSClientConfig: clientTLSConf,
}
http := http.Client{
Transport: transport,
}
resp, err := http.Get(server.URL)
if err != nil {
panic(err)
}
// verify the response
respBodyBytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
panic(err)
}
body := strings.TrimSpace(string(respBodyBytes[:]))
if body == "success!" {
fmt.Println(body)
} else {
panic("not successful!")
}
}
func certsetup() (serverTLSConf *tls.Config, clientTLSConf *tls.Config, err error) {
// set up our CA certificate
ca := &x509.Certificate{
SerialNumber: big.NewInt(2019),
Subject: pkix.Name{
Organization: []string{"Company, INC."},
Country: []string{"US"},
Province: []string{""},
Locality: []string{"San Francisco"},
StreetAddress: []string{"Golden Gate Bridge"},
PostalCode: []string{"94016"},
},
NotBefore: time.Now(),
NotAfter: time.Now().AddDate(10, 0, 0),
IsCA: true,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
BasicConstraintsValid: true,
}
// create our private and public key
caPrivKey, err := rsa.GenerateKey(rand.Reader, 4096)
if err != nil {
return nil, nil, err
}
// create the CA
caBytes, err := x509.CreateCertificate(rand.Reader, ca, ca, &caPrivKey.PublicKey, caPrivKey)
if err != nil {
return nil, nil, err
}
// pem encode
caPEM := new(bytes.Buffer)
pem.Encode(caPEM, &pem.Block{
Type: "CERTIFICATE",
Bytes: caBytes,
})
caPrivKeyPEM := new(bytes.Buffer)
pem.Encode(caPrivKeyPEM, &pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: x509.MarshalPKCS1PrivateKey(caPrivKey),
})
// set up our server certificate
cert := &x509.Certificate{
SerialNumber: big.NewInt(2019),
Subject: pkix.Name{
Organization: []string{"Company, INC."},
Country: []string{"US"},
Province: []string{""},
Locality: []string{"San Francisco"},
StreetAddress: []string{"Golden Gate Bridge"},
PostalCode: []string{"94016"},
},
IPAddresses: []net.IP{net.IPv4(127, 0, 0, 1), net.IPv6loopback},
NotBefore: time.Now(),
NotAfter: time.Now().AddDate(10, 0, 0),
SubjectKeyId: []byte{1, 2, 3, 4, 6},
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
KeyUsage: x509.KeyUsageDigitalSignature,
}
certPrivKey, err := rsa.GenerateKey(rand.Reader, 4096)
if err != nil {
return nil, nil, err
}
certBytes, err := x509.CreateCertificate(rand.Reader, cert, ca, &certPrivKey.PublicKey, caPrivKey)
if err != nil {
return nil, nil, err
}
certPEM := new(bytes.Buffer)
pem.Encode(certPEM, &pem.Block{
Type: "CERTIFICATE",
Bytes: certBytes,
})
certPrivKeyPEM := new(bytes.Buffer)
pem.Encode(certPrivKeyPEM, &pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: x509.MarshalPKCS1PrivateKey(certPrivKey),
})
serverCert, err := tls.X509KeyPair(certPEM.Bytes(), certPrivKeyPEM.Bytes())
if err != nil {
return nil, nil, err
}
serverTLSConf = &tls.Config{
Certificates: []tls.Certificate{serverCert},
}
certpool, _ := x509.SystemCertPool()
if certpool == nil {
certpool = x509.NewCertPool()
}
certpool.AppendCertsFromPEM(caPEM.Bytes())
clientTLSConf = &tls.Config{
InsecureSkipVerify: true,
}
return
}
现在我如何将它分成 2 个文件,如 server.go 和 client.go
这里它使用 httptest.NewUnstartedServer 而不是我想使用 ListenAndServeTLS 或一些类似的方法如何实现。
【问题讨论】:
-
你试过什么?有一个明确的部分处理
client和server。 -
只是一些代码到 server.go 中,其余的到 client.go 中?
-
嗨@shreyas。欢迎来到堆栈溢出。作为新的贡献者,我正在审查您的问题。我可以建议对您的问题进行一些更改吗? 1)你能解释一下为什么你被卡住了吗?是什么让你想问这个问题?是什么让你很难做到这一点? 2)解释为什么你试图将代码分成两个文件? 3) 你是 Golang 新手吗?对编程本身不熟悉?解释这些要点。 4)改写你的问题首先出现,即“现在我如何将它分成两个文件,如 server.go 和 client.go”。还要确保您的标题反映了实际问题。