Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ssl/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Go中创建使用TLS客户端身份验证的测试服务器?_Go_Ssl_X509_Pem_Ssl Client Authentication - Fatal编程技术网

如何在Go中创建使用TLS客户端身份验证的测试服务器?

如何在Go中创建使用TLS客户端身份验证的测试服务器?,go,ssl,x509,pem,ssl-client-authentication,Go,Ssl,X509,Pem,Ssl Client Authentication,我想为HTTP处理程序编写一个单元测试,它从设备的证书中提取某些信息。我找到了这个要点,它使用openssl生成证书,并在client.go和server.go中读取生成的文件。然而,为了使事情更加透明,我想使用Go的标准库生成证书 以下是我到目前为止对单元测试的尝试(可从以下网址获得): 主程序包 进口( “加密” “加密/兰德” “加密/rsa” “加密/sha1” “加密/tls” “加密/x509” “加密/x509/pkix” “编码/asn1” “编码/pem” “io” “数学/大

我想为HTTP处理程序编写一个单元测试,它从设备的证书中提取某些信息。我找到了这个要点,它使用
openssl
生成证书,并在
client.go
server.go
中读取生成的文件。然而,为了使事情更加透明,我想使用Go的标准库生成证书

以下是我到目前为止对单元测试的尝试(可从以下网址获得):

主程序包
进口(
“加密”
“加密/兰德”
“加密/rsa”
“加密/sha1”
“加密/tls”
“加密/x509”
“加密/x509/pkix”
“编码/asn1”
“编码/pem”
“io”
“数学/大”
“净额”
“net/http”
“net/http/httptest”
“测试”
“时间”
“github.com/stretchr/authentic/assert”
“github.com/stretchr/authentic/require”
)
func TestDeviceFromTLS(t*testing.t){
deviceKeyPEM,csrPEM:=发电机和CSR(t)
caKey,caKeyPEM:=发电机(t)
caCert,caCertPEM:=生成器OTCERT(t,caKey)
deviceCertPEM:=signCSR(t、csrPEM、caKey、caCert)
serverCert,err:=tls.X509KeyPair(caCertPEM,caKeyPEM)
require.NoError(t,err)
clientPool:=x509.NewCertPool()
clientPool.AddCert(caCert)
ts:=httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter,r*http.Request){
assert.Len(t,r.TLS.PeerCertificates,1)
}))
ts.TLS=&TLS.Config{
证书:[]tls.Certificate{serverCert},
客户授权:tls.RequiredVerifyClientCert,
ClientCAs:clientPool,
}
t.StartTLS()
延迟ts关闭()
deviceCert,err:=tls.X509KeyPair(deviceCertPEM,deviceKeyPEM)
require.NoError(t,err)
池:=x509.NewCertPool()
pool.AddCert(caCert)
客户端:=ts.client()
client.Transport.(*http.Transport).TLSClientConfig=&tls.Config{
证书:[]tls.Certificate{deviceCert},
RootCAs:pool,
}
req,err:=http.NewRequest(http.MethodPut,ts.URL,nil)
resp,err:=client.Do(请求)
require.NoError(t,err)
延迟响应主体关闭()
assert.justice(t、http.StatusOK、resp.StatusCode)
}
func generateKeyAndCSR(t*testing.t)([]字节,[]字节){
rsaKey,err:=rsa.GenerateKey(rand.Reader,1024)
require.NoError(t,err)
键:=pem.encodetomery(&pem.Block){
键入:“RSA私钥”,
字节:x509.MarshallPKCS1PrivateKey(rsaKey),
})
模板:=&x509.CertificateRequest{
主题:pkix.Name{
国家:[]字符串{“US”},
地点:[]字符串{“旧金山”},
组织:[]字符串{“Awesomeness,Inc.”,
省:[]字符串{“加利福尼亚”},
},
签名算法:x509.SHA256,带RSA,
IP地址:[]net.IP{net.ParseIP(“127.0.0.1”)},
}
请求,错误:=x509.CreateCertificateRequest(rand.Reader,template,rsaKey)
require.NoError(t,err)
csr:=pem.encodetomery(&pem.Block){
类型:“证书请求”,
字节:req,
})
返回键
}
func generateRootCert(t*testing.t,key crypto.Signer)(*x509.Certificate,[]字节){
subjectKeyIdentifier:=calculateSubjectKeyIdentifier(t,key.Public())
模板:=&x509.0证书{
序列号:generateSerial(t),
主题:pkix.Name{
组织:[]字符串{“Awesomeness,Inc.”,
国家:[]字符串{“US”},
地点:[]字符串{“旧金山”},
},
NotBefore:time.Now(),
NotAfter:time.Now().AddDate(10,0,0),
SubjectKeyId:subjectKeyIdentifier,
AuthorityKeyId:subjectKeyIdentifier,
KeyUsage:x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
ExtKeyUsage:[]x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth,x509.ExtKeyUsageClientAuth},
BasicConstraintsValid:true,
IsCA:是的,
MaxPathLenZero:对,
}
der,err:=x509.CreateCertificate(rand.Reader,template,template,key.Public(),key)
require.NoError(t,err)
rootCert,err:=x509.ParseCertificate(der)
require.NoError(t,err)
rootCertPEM:=pem.EncodeToMemory(&pem.Block){
键入:“证书”,
字节:der,
})
返回rootCert,rootCertPEM
}
//generateSerial使用RFC 5280 4.1.2.2允许的最大八位字节数(20)生成序列号
//(改编自https://github.com/cloudflare/cfssl/blob/828c23c22cbca1f7632b9ba85174aaa26e745340/signer/local/local.go#L407-L418)
函数生成序列(t*testing.t)*big.Int{
serialNumber:=生成([]字节,20)
_,err:=io.ReadFull(rand.Reader,serialNumber)
require.NoError(t,err)
返回新的(big.Int).SetBytes(serialNumber)
}
//calculateSubjectKeyIdentifier实现了一种生成密钥标识符的通用方法
//从公钥,即,通过从位字符串的160位SHA-1散列组成公钥
//公开密钥(参见。https://tools.ietf.org/html/rfc5280#section-4.2.1.2).
//(改编自https://github.com/jsha/minica/blob/master/main.go).
func计算subjectKeyIdentifier(t*testing.t,pubKey crypto.PublicKey)[]字节{
spkiASN1,错误:=x509.MarshallPKIxPublicKey(公钥)
require.NoError(t,err)
var-spki结构{
算法pkix.AlgorithmIdentifier
SubjectPublicKey asn1.BitString
}
_,err=asn1.Unmarshal(spkiASN1和spki)
require.NoError(t,err)
滑动:=sha1.Sum(spki.SubjectPublicKey.Bytes)
返回滑轨[:]
}
//signCSR使用给定的CA证书和私钥对证书签名请求进行签名
func signCSR(t*testing.t,csr[]字节,caKey crypto.Signer,caCert*x509.Certificate)[]字节{
块:=pem.Decode(csr)
require.NotNil(t,块,“未能解码CSR”)
certificateRequest,err:=x509.ParseCertificateRequest(block.Bytes)
诺埃罗先生
> go test ./...
2020/04/06 15:12:30 http: TLS handshake error from 127.0.0.1:58685: remote error: tls: bad certificate
--- FAIL: TestDeviceFromTLS (0.05s)
    main_test.go:64: 
            Error Trace:    main_test.go:64
            Error:          Received unexpected error:
                            Put https://127.0.0.1:58684: x509: cannot validate certificate for 127.0.0.1 because it doesn't contain any IP SANs
            Test:           TestDeviceFromTLS
FAIL
FAIL    github.com/kurtpeek/client-auth-test    0.379s
caKey, caKeyPEM := generateKey(t)
caCert, caCertPEM := generateRootCert(t, caKey)

serverCert, err := tls.X509KeyPair(caCertPEM, caKeyPEM)