Golang - 带自签名证书的TLS

时间:2014-03-26 15:43:26

标签: ssl go

我正在尝试使用自签名服务器证书建立TLS连接。

我使用以下示例代码生成证书:http://golang.org/src/pkg/crypto/tls/generate_cert.go

我的相关客户端代码如下:

// server cert is self signed -> server_cert == ca_cert
CA_Pool := x509.NewCertPool()
severCert, err := ioutil.ReadFile("./cert.pem")
if err != nil {
    log.Fatal("Could not load server certificate!")
}
CA_Pool.AppendCertsFromPEM(severCert)

config := tls.Config{RootCAs: CA_Pool}

conn, err := tls.Dial("tcp", "127.0.0.1:8000", &config)
if err != nil {
    log.Fatalf("client: dial: %s", err)
}

相关的服务器代码如下:

cert, err := tls.LoadX509KeyPair("./cert.pem", "./key.pem")
config := tls.Config{Certificates: []tls.Certificate{cert}}
listener, err := tls.Listen("tcp", "127.0.0.1:8000", &config)

for {
    conn, err := listener.Accept()
    if err != nil {
        log.Printf("server: accept: %s", err)
        break
    }
    log.Printf("server: accepted from %s", conn.RemoteAddr())
    go handleConnection(conn)
}

因为服务器证书是自签名的,所以使用与服务器和客户端CA_Pool相同的证书,但这似乎不起作用,因为我总是收到此错误:

client: dial: x509: certificate signed by unknown authority 
(possibly because of "x509: invalid signature: parent certificate
cannot sign this kind of certificate" while trying to verify 
candidate authority certificate "serial:0")

我的错误是什么?

6 个答案:

答案 0 :(得分:25)

它最终适用于x509.CreateCertificate中构建的go, 问题是我没有设置IsCA:true flag 我只设置了x509.KeyUsageCertSign ,这使得创建自签名证书有效,但在验证证书链时崩溃了。

答案 1 :(得分:10)

问题是您需要在服务器端配置中使用CA证书,并且此CA必须已签署服务器证书。

我已经编写了一些将generate作为CA证书的Go代码,但它尚未经过任何人的审核,而且主要是用于玩客户端证书的玩具。最安全的赌注可能是使用openssl ca生成并签署证书。基本步骤将是:

  1. 生成CA证书
  2. 生成服务器密钥
  3. 使用CA证书签署服务器密钥
  4. 将CA证书添加到客户端的tls.Config RootCAs
  5. 使用服务器密钥和签名证书设置服务器的tls.Config

答案 2 :(得分:4)

凯尔,是对的。该工具可以满足您的需求,简化了整个过程:

https://github.com/deckarep/EasyCert/releases(仅支持OSX,因为它在内部使用openssl工具)

和来源:

https://github.com/deckarep/EasyCert

基本上使用这个工具,它会生成一个文件包,但是你需要它完成时输出的三个文件。

  1. CA根cer文件
  2. 服务器cer文件
  3. 服务器密钥文件

答案 3 :(得分:0)

我在golang中使用mysql客户端时看到了相同的错误:

True

并将Failed to connect to database: x509: cannot validate certificate for 10.111.202.229 because it doesn't contain any IP SANs 设置为InsecureSkipVerify(以跳过证书验证)为我解决了这个问题:

https://godoc.org/crypto/tls#Config

以下代码对我有用:

true

答案 4 :(得分:0)

就我而言,我附加的证书未正确编码为pem格式。 如果使用keytools,请确保在从密钥库中导出证书时附加-rfc,可以在文本编辑器中打开编码的pem以显示:

-----BEGIN CERTIFICATE----- MIIDiDCCAnCgAwIBAgIEHKSkvDANBgkqhkiG9w0BAQsFADBi...

答案 5 :(得分:-1)

您需要使用InsecureSkipVerify标志,请参阅https://groups.google.com/forum/#!topic/golang-nuts/c9zEiH6ixyw

此帖子的相关代码(包含页面离线):

smtpbox := "mail.foo.com:25"
c, err := smtp.Dial(smtpbox)

host, _, _ := net.SplitHostPort(smtpbox)
tlc := &tls.Config{
    InsecureSkipVerify: true,
    ServerName:         host,
}
if err = c.StartTLS(tlc); err != nil {
    fmt.Printf(err)
    os.Exit(1)
} 
// carry on with rest of smtp transaction 
// c.Auth, c.Mail, c.Rcpt, c.Data, etc