【问题标题】:TLS with selfsigned certificate带有自签名证书的 TLS
【发布时间】:2014-05-05 03:50:39
【问题描述】:

我正在尝试使用自签名服务器证书建立 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")

我的错误是什么?

【问题讨论】:

    标签: ssl go


    【解决方案1】:

    它终于与内置于 x509.CreateCertificate 的 go 一起工作了, 问题是 我没有设置 IsCA:true 标志我只设置了 x509.KeyUsageCertSign,它使创建自签名证书工作,但在验证证书链时崩溃。

    【讨论】:

    • 谢谢 Zap,这帮助我指出了如何解决这个问题的方向,我发布了一个简短的自包含的 ansible 自动化解决方案 + 解释示例,作为另一个相关问题的答案,我不知道'不想重复我的答案,所以我链接到其他相关的问答。 stackoverflow.com/questions/34288371/…
    【解决方案2】:

    问题是你需要在服务器端配置一个CA 证书,而且这个CA 必须已经签署了服务器的证书。

    我已经编写了一些将generate CA 证书的 Go 代码,但它没有经过任何人的审查,并且主要是一个玩弄客户端证书的玩具。最安全的选择可能是使用openssl ca 来生成和签署证书。基本步骤是:

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

    【讨论】:

      【解决方案3】:

      凯尔,是正确的。这个工具会做你想做的,它简化了整个过程:

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

      来源:

      https://github.com/deckarep/EasyCert

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

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

      【讨论】:

      • 好的,我使用了 EasyCert 但现在我得到一个:“客户端:拨号:x509:无法验证 127.0.0.1 的证书,因为它不包含任何 IP SAN”什么是 IS SAN
      • 我要冒昧地说你可能在 Go 中遇到了一个错误:code.google.com/p/go/issues/detail?id=4658 如果可能的话,也许尝试升级你的 Go 版本。
      【解决方案4】:

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

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

      【讨论】:

        【解决方案5】:

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

        Failed to connect to database:  x509: cannot validate certificate for 10.111.202.229 because it doesn't contain any IP SANs
        

        并将InsecureSkipVerify 设置为true(跳过证书验证)为我解决了这个问题:

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

        以下代码对我有用:

        package main
        
        import (
         "fmt"
         "github.com/go-sql-driver/mysql"
         "github.com/jinzhu/gorm"
         "crypto/tls"
         "crypto/x509"
         "io/ioutil"
         "log"
        )
        
        func main() {
            rootCertPool := x509.NewCertPool()
            pem, err := ioutil.ReadFile("/usr/local/share/ca-certificates/ccp-root-ca.crt")
            if err != nil {
                    log.Fatal(err)
            }
            if ok := rootCertPool.AppendCertsFromPEM(pem); !ok {
                log.Fatal("Failed to append root CA cert at /usr/local/share/ca-certificates/ccp-root-ca.crt.")
            }
            mysql.RegisterTLSConfig("custom", &tls.Config{
                RootCAs: rootCertPool,
                InsecureSkipVerify: true,
            })
        
            db, err := gorm.Open("mysql", "ccp-user:I6qnD6zNDmqdDLXYg3HqVAk2P@tcp(10.111.202.229:3306)/ccp?tls=custom")
            defer db.Close()
        }
        

        【讨论】:

          【解决方案6】:

          您需要使用 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
          

          【讨论】:

          • 您应该验证 SSL 证书,而不是仅仅接受任何 SSL 证书。
          • 这是一个重要的测试解决方法,确实帮助我了解。谢谢!
          • InsecureSkipVerify 的意思是“安全 = 关闭”。这会使您遭受 MITM 攻击。这仅对开发是安全的!
          • 开发测试的好选择。
          猜你喜欢
          • 2015-02-09
          • 2018-12-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-06-18
          • 1970-01-01
          相关资源
          最近更新 更多