Golang中ListenAndServeTLS使用拼接证书(公钥+CA)时遇到的私钥问题

Golang中ListenAndServeTLS使用拼接证书(公钥+CA)时遇到的私钥问题 大家好,

首先我想道歉,这可能不是一个直接与Go相关的问题,但我猜有些人可能遇到过类似的问题。

我想为我的Web项目使用SSL;我有一个foo.bar域的证书(通过CPanel安装SSL,由Comodo签发)。我有私钥、公钥和CA证书。根据文档的理解,我应该将公钥和CA证书拼接起来;否则,目前对于每个请求我都会收到"http: TLS handshake error from a.b.c.d:x: remote error: tls: unknown certificate authority"错误。

我的TLS配置如下:

cfg := &tls.Config{
	MinVersion:               tls.VersionTLS12,
	CurvePreferences:         []tls.CurveID{tls.CurveP521, tls.CurveP384, tls.CurveP256},
	PreferServerCipherSuites: true,
	CipherSuites: []uint16{
		tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
		tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
		tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
		tls.TLS_RSA_WITH_AES_256_CBC_SHA,
	},
	ServerName:				"foo.bar",
}

但是,当我手动拼接这些证书或使用我的CA提供的"捆绑"证书时,我收到"tls: private key does not match public key"错误。

所以,基本上,拥有私钥、公钥证书和CA证书的情况下,获取捆绑/拼接证书的"新"密钥的正确方法是什么?还是我从一开始就做错了什么?

提前感谢任何帮助或提示,

编辑: 显然,这是解决方案(至少在我的情况下)- 我最初得到了两个证书文件:一个是"捆绑包",另一个是证书本身。我的误解是认为"捆绑包"已经包含了我的foo.bar证书。但事实是,foo.bar证书必须作为"终端实体"添加到前面提到的捆绑包中。这样,我的私钥就能按预期工作,Go SSL服务器支持也能正常工作!

希望这能帮助到其他人!


更多关于Golang中ListenAndServeTLS使用拼接证书(公钥+CA)时遇到的私钥问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于Golang中ListenAndServeTLS使用拼接证书(公钥+CA)时遇到的私钥问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Golang中使用ListenAndServeTLS时遇到"private key does not match public key"错误,通常是因为证书链配置不正确。根据你的描述,问题在于证书拼接的顺序和内容。

正确的证书链应该按照以下顺序拼接:

  1. 你的域名证书(公钥)
  2. 中间CA证书
  3. 根CA证书

以下是一个完整的示例代码:

package main

import (
    "crypto/tls"
    "net/http"
)

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte("Hello, TLS!"))
    })

    // 加载证书和私钥
    certFile := "path/to/your/certificate.pem"    // 包含域名证书和CA证书链
    keyFile := "path/to/your/private.key"         // 私钥文件

    // TLS配置
    cfg := &tls.Config{
        MinVersion:               tls.VersionTLS12,
        CurvePreferences:         []tls.CurveID{tls.CurveP521, tls.CurveP384, tls.CurveP256},
        PreferServerCipherSuites: true,
        CipherSuites: []uint16{
            tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
            tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
            tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
            tls.TLS_RSA_WITH_AES_256_CBC_SHA,
        },
    }

    server := &http.Server{
        Addr:      ":443",
        TLSConfig: cfg,
    }

    // 启动TLS服务器
    err := server.ListenAndServeTLS(certFile, keyFile)
    if err != nil {
        panic(err)
    }
}

证书文件应该这样拼接:

# 创建正确的证书链文件
cat domain_cert.pem intermediate_ca.pem root_ca.pem > certificate.pem

验证证书和私钥是否匹配的方法:

// 验证证书和私钥是否匹配
func verifyCertKey(certFile, keyFile string) error {
    _, err := tls.LoadX509KeyPair(certFile, keyFile)
    return err
}

如果你的证书文件格式正确,LoadX509KeyPair函数会成功加载证书对而不会报错。确保私钥文件是PEM格式,并且没有被加密(或者如果加密了,需要提供密码)。

证书链的顺序至关重要:你的域名证书必须放在最前面,然后是中间CA证书,最后是根CA证书。任何顺序错误都会导致TLS握手失败。

回到顶部