go tls证书 制作自签名证书(转发自别的大佬的)
CA
为了保证证书的可靠性和有效性,在这里可引入 CA 颁发的根证书的概念。CA就是专门用自己的私钥给别人进行签名的单位或者机构,其遵守 X.509 标准,即无论是客户端还是服务端都是使用CA来签发证书。
根证书
根证书(root certificate)是属于根证书颁发机构(CA)的公钥证书。我们可以通过验证 CA 的签名从而信任 CA ,任何人都可以得到 CA 的证书(含公钥),用以验证它所签发的证书(客户端、服务端)。
它包含了公钥和密钥。
CA公钥
进入cert目录
openssl genrsa -out ca.key 2048
- openssl genrsa:生成RSA私钥,命令的最后一个参数,将指定生成密钥的位数,如果没有指定,默认512
CA秘钥(证书)
openssl req -new -x509 -days 365 -key ca.key -out ca.pem
-x509:证书文件格式为x509,目前TLS默认只支持这种格式的证书-days 365:证书有效期1年-out ca.pem:生成的私钥保存到ca.pem
要填写的信息:
Country Name (2 letter code) [XX]:
State or Province Name (full name) []:
Locality Name (eg, city) [Default City]:
Organization Name (eg, company) [Default Company Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:ca.com
Email Address []:
- 生成的过程中会要求填一些信息,除了Common Name要取一个容易区分的名字之外,其它都可以随便填写,我们在这里将它填为ca.com.
服务器证书相关
服务器key
# openssl genrsa -out server.key 2048
或者
openssl ecparam -genkey -name secp384r1 -out server.key
openssl genrsa:生成RSA私钥,命令的最后一个参数,将指定生成密钥的位数,如果没有指定,默认512openssl ecparam:生成ECC私钥,命令为椭圆曲线密钥参数生成及操作,本文中ECC曲线选择的是secp384r1
生成 CSR(证书申请文件)
CSR 是**Cerificate Signing Request **的英文缩写,为证书申请文件,在服务器私钥的基础上加上一些申请人的属性信息,比如我是谁,来自哪里,名字叫什么,证书适用于什么场景等的信息,然后带上进行的签名,发给CA(私下安全的方式发送),带上自己签名的目的是为了防止别人篡改文件。
openssl req -new -key server.key -out server.csr
要填写的信息:
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:domain.com
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:123456
An optional company name []:
- 生成的过程中会要求填一些信息,除了Common Name要取一个容易区分的名字之外,其它都可以随便填写,我们在这里将它填为domain.com;
- 密码也是建议填写;
- 注意和ca证书的不同。
基于 CA 签发
使用CA的公钥对申请文件进行签名
openssl x509 -req -sha256 -CA ca.pem -CAkey ca.key -CAcreateserial -days 3650 -in server.csr -out server.pem
-sha256:生成的证书里面使用sha256作为摘要算法- 由于需要往生成的证书里写入签名者的信息,所以这里需要ca.pem,因为只有这里有CA的描述信息,ca.key里面只有公钥的信息。
客户端证书相关
此生成的证书可用于浏览器、java、tomcat、golang等。
客户端key
openssl ecparam -genkey -name secp384r1 -out client.key
生成CSR(证书申请书)
openssl req -new -key client.key -out client.csr
要填写的信息:
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:domain.com
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:123456
An optional company name []:
Common Name要取一个容易区分的名字之外,填为domain.com,和服务器的CSR保持一致;- 密码也是建议填写;
- 注意和ca证书的不同。
基于CA签发
openssl x509 -req -sha256 -CA ca.pem -CAkey ca.key -CAcreateserial -days 3650 -in client.csr -out client.pem
生成客户端p12格式根证书
该证书用于导入浏览器使用。
openssl pkcs12 -export -clcerts -in client.pem -inkey client.key -out client.p12
golang服务端
目录
grpc-tls/
├── configs
│ ├── cert # 存放证书相关的目录
│ ├── ca.key
│ └── ca.pem # 导入浏览器使用
│ ├── server.csr
│ └── server.key
│ └── server.pem
│ ├── client.csr
│ └── client.key
│ └── client.pem
│ └── client.p12 # 导入浏览器使用
├── cmd
│ ├── main.go
main.go
package main
import (
"crypto/tls"
"crypto/x509"
"github.com/gin-gonic/gin"
"io/ioutil"
"log"
"net/http"
"time"
)
func main() {
router := gin.Default()
router.GET("/test", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "test",
})
})
// 启动https方式访问
cert, err := tls.LoadX509KeyPair("./configs/cert/server.pem", "./configs/cert/server.key")
if err != nil {
log.Fatalf("tls.LoadX509KeyPair err: %v", err)
}
certPool := x509.NewCertPool()
ca, err := ioutil.ReadFile("./configs/cert/ca.pem")
if err != nil {
log.Fatalf("ioutil.ReadFile err: %v", err)
}
if ok := certPool.AppendCertsFromPEM(ca); !ok {
log.Fatalf("certPool.AppendCertsFromPEM err")
}
ReadTimeout := time.Duration(60) * time.Second
WriteTimeout := time.Duration(60) * time.Second
s := &http.Server{
Addr: ":8090",
Handler: router,
ReadTimeout: ReadTimeout,
WriteTimeout: WriteTimeout,
MaxHeaderBytes: 1 << 20,
TLSConfig:&tls.Config{
Certificates: []tls.Certificate{cert},
MinVersion: tls.VersionTLS12,
ClientAuth: tls.RequireAndVerifyClientCert,
ClientCAs: certPool,
},
}
s.ListenAndServeTLS("./configs/cert/server.pem","./configs/cert/server.key")
}
golang客户端
main.go
package main
import (
"crypto/tls"
"crypto/x509"
"io/ioutil"
"log"
)
func main() {
cert, err := tls.LoadX509KeyPair("client.pem", "client.key")
if err != nil {
log.Println(err)
return
}
certBytes, err := ioutil.ReadFile("client.pem")
if err != nil {
panic("Unable to read cert.pem")
}
clientCertPool := x509.NewCertPool()
ok := clientCertPool.AppendCertsFromPEM(certBytes)
if !ok {
panic("failed to parse root certificate")
}
conf := &tls.Config{
RootCAs: loadCA("ca.pem"),
Certificates: []tls.Certificate{cert},
InsecureSkipVerify: true,
}
conn, err := tls.Dial("tcp", "127.0.0.1:443", conf)
if err != nil {
log.Println(err)
return
}
defer conn.Close()
n, err := conn.Write([]byte("hello\n"))
if err != nil {
log.Println(n, err)
return
}
buf := make([]byte, 100)
n, err = conn.Read(buf)
if err != nil {
log.Println(n, err)
return
}
println(string(buf[:n]))
}
func loadCA(caFile string) *x509.CertPool {
pool := x509.NewCertPool()
if ca, e := ioutil.ReadFile(caFile); e != nil {
log.Fatal("ReadFile: ", e)
} else {
pool.AppendCertsFromPEM(ca)
}
return pool
}
浙公网安备 33010602011771号