TLS with selfsigned certificate

2020-02-02 04:15发布

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:

// 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)
}

And the relevant server code like that:

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)
}

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 "x509: invalid signature: parent certificate
cannot sign this kind of certificate" while trying to verify 
candidate authority certificate "serial:0")

What's my mistake?

标签: ssl go
6条回答
beautiful°
2楼-- · 2020-02-02 04:54

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楼-- · 2020-02-02 04:57

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
查看更多
Animai°情兽
4楼-- · 2020-02-02 04:58

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'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 (
 "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()
}
查看更多
趁早两清
5楼-- · 2020-02-02 05:01

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楼-- · 2020-02-02 05:08

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 := "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
查看更多
放荡不羁爱自由
7楼-- · 2020-02-02 05:20

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.

查看更多
登录 后发表回答