使用自签名证书的TLS

huangapple go评论104阅读模式
英文:

TLS with selfsigned certificate

问题

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

我犯了什么错误?

英文:

I'm trying to establish a TLS connection with the use of a self signed server certificate.

I generated the certificate with this example code: http://golang.org/src/pkg/crypto/tls/generate_cert.go

My relevant client code looks like that:

<!-- language: go -->

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

config := tls.Config{RootCAs: CA_Pool}

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

And the relevant server code like that:

<!-- language: go-->

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

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

Because the server certificate is self signed is use the same certificate for the server and the clients CA_Pool however this does not seem to work since i always get this error:

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

What's my mistake?

答案1

得分: 36

最终使用内置的x509.CreateCertificate函数成功了,问题在于我没有设置IsCA:true标志我只设置了x509.KeyUsageCertSign,这使得创建自签名证书可以工作,但在验证证书链时崩溃了。

英文:

It finally worked with the go built in x509.CreateCertificate,
the problem was that I did not set the IsCA:true flag,
I only set the x509.KeyUsageCertSign which made creating the self signed certificate work, but crashed while verifying the cert chain.

答案2

得分: 9

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

我编写了一些Go代码,可以生成一个CA证书,但是它还没有经过任何人的审核,主要是用来玩弄客户端证书的玩具。最安全的方法可能是使用openssl ca来生成和签署证书。基本步骤如下:

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

The problem is that you need a CA certificate in the server-side config, and this CA must have signed the server's certificate.

I have written some Go code that will generate a CA certificate, but it hasn't been reviewed by anyone and is mostly a toy for playing around with client certs. The safest bet is probably to use openssl ca to generate and sign the certificate. The basic steps will be:

  1. Generate a CA Certificate
  2. Generate a Server key
  3. Sign the Server key with the CA certificate
  4. Add the CA Certificate to the client's tls.Config RootCAs
  5. Set up the server's tls.Config with the Server key and signed certificate.

答案3

得分: 4

Kyle是正确的。这个工具可以满足你的需求,并且简化了整个过程:

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

以及源代码:

https://github.com/deckarep/EasyCert

使用这个工具,它会生成一组文件,但你只需要在完成后使用其中的三个文件:

  1. 一个CA根证书文件
  2. 一个服务器证书文件
  3. 一个服务器密钥文件
英文:

Kyle, is correct. This tool will do what you want and it simplifies the entire process:

https://github.com/deckarep/EasyCert/releases (only OSX is supported since it uses the openssl tool internally)

and the source:

https://github.com/deckarep/EasyCert

Basically with this tool it will generate a bundle of files but you will need the three that it outputs when it's done.

  1. a CA root cer file
  2. a Server cer file
  3. a Server key file

答案4

得分: 0

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

无法连接到数据库:x509: 无法验证证书10.111.202.229,因为它不包含任何IP SAN

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()
}
英文:

I saw the same error when using mysql client in Go:

Failed to connect to database:  x509: cannot validate certificate for 10.111.202.229 because it doesn&#39;t contain any IP SANs

and setting InsecureSkipVerify to true (to skip verification of certificate) resolved it for me:

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

The following code worked for me:

package main

import (
 &quot;fmt&quot;
 &quot;github.com/go-sql-driver/mysql&quot;
 &quot;github.com/jinzhu/gorm&quot;
 &quot;crypto/tls&quot;
 &quot;crypto/x509&quot;
 &quot;io/ioutil&quot;
 &quot;log&quot;
)

func main() {
	rootCertPool := x509.NewCertPool()
	pem, err := ioutil.ReadFile(&quot;/usr/local/share/ca-certificates/ccp-root-ca.crt&quot;)
	if err != nil {
		    log.Fatal(err)
	}
	if ok := rootCertPool.AppendCertsFromPEM(pem); !ok {
		log.Fatal(&quot;Failed to append root CA cert at /usr/local/share/ca-certificates/ccp-root-ca.crt.&quot;)
	}
	mysql.RegisterTLSConfig(&quot;custom&quot;, &amp;tls.Config{
		RootCAs: rootCertPool,
		InsecureSkipVerify: true,
	})

	db, err := gorm.Open(&quot;mysql&quot;, &quot;ccp-user:I6qnD6zNDmqdDLXYg3HqVAk2P@tcp(10.111.202.229:3306)/ccp?tls=custom&quot;)
	defer db.Close()
}

答案5

得分: 0

在我的情况下,我附加的证书在 pem 格式中没有正确编码。如果使用 keytools,确保在从密钥库导出证书时附加 -rfc,以便可以在文本编辑器中打开 pem 编码的证书进行显示:

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

英文:

In my case, the certificate I appended was not encoded correctly in pem format.
If using keytools, ensure to append -rfc while exporting the certificate from keystore, pem encoded could be opened in a text editor to display:

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

答案6

得分: -2

你需要使用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)
} 
// 继续进行其余的smtp事务
// c.Auth, c.Mail, c.Rcpt, c.Data, 等等
英文:

You need to use the InsecureSkipVerify flag, refer to https://groups.google.com/forum/#!topic/golang-nuts/c9zEiH6ixyw.

The related code of this post (incase the page is offline):

smtpbox := &quot;mail.foo.com:25&quot;
c, err := smtp.Dial(smtpbox)

host, _, _ := net.SplitHostPort(smtpbox)
tlc := &amp;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

huangapple
  • 本文由 发表于 2014年3月26日 23:43:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/22666163.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定