英文:
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 -> 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:
<!-- language: go-->
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?
答案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
来生成和签署证书。基本步骤如下:
- 生成一个CA证书
- 生成一个服务器密钥
- 使用CA证书签署服务器密钥
- 将CA证书添加到客户端的
tls.Config
的RootCAs
中 - 使用服务器密钥和签署的证书设置服务器的
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:
- Generate a CA Certificate
- Generate a Server key
- Sign the Server key with the CA certificate
- Add the CA Certificate to the client's
tls.Config
RootCAs
- 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
使用这个工具,它会生成一组文件,但你只需要在完成后使用其中的三个文件:
- 一个CA根证书文件
- 一个服务器证书文件
- 一个服务器密钥文件
英文:
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.
- a CA root cer file
- a Server cer file
- 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'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
得分: 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 := "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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论