SSL TLS

PPG007 ... 2022-5-6 About 2 min

# SSL TLS

流程:服务端具有一个公钥和一个私钥,首先服务端创建证书签名 CSR,其中包含服务端的公钥和一些身份信息,然后服务端使用私钥签署了 CSR 并发送给 CA,CA 使用服务端的公钥验证 CSR 签名,这样就验证了一对对应的私钥和公钥,之后(此时证书应该不是被服务单私钥加密的状态) CA 使用自己的私钥在证书上签名然后返回给服务端,服务端与客户端共享这个证书,客户端可以使用 CA 的公钥对证书进行验证并获取到服务端的公钥。

首先使用 OpenSSL 生成 CA 密钥和证书、服务端密钥和证书、客户端密钥和证书:

# 1. Generate CA's private key and self-signed certificate
openssl req -x509 -newkey rsa:4096 -days 365 -nodes -keyout ca-key.pem -out ca-cert.pem -subj "/C=CN/ST=ShanDong/L=QingDao/O=company/OU=demo/CN=koston/emailAddress=koston.zhuang@demo.com"

# 2. Generate web server's private key and certificate signing request (CSR)
openssl req -newkey rsa:4096 -nodes -keyout server-key.pem -out server-req.pem -subj "/C=CN/ST=ShanDong/L=QingDao/O=company/OU=demo/CN=koston/emailAddress=koston.zhuang@demo.com"

# 3. Use CA's private key to sign web server's CSR and get back the signed certificate
openssl x509 -req -in server-req.pem -days 60 -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -extfile server-ext.cnf

# 4. Generate client's private key and certificate signing request (CSR)
openssl req -newkey rsa:4096 -nodes -keyout client-key.pem -out client-req.pem -subj "/C=CN/ST=ShanDong/L=QingDao/O=company/OU=demo/CN=koston/emailAddress=koston.zhuang@demo.com"

# 5. Use CA's private key to sign client's CSR and get back the signed certificate
openssl x509 -req -in client-req.pem -days 60 -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out client-cert.pem -extfile client-ext.cnf
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 服务端认证

修改服务端启动函数:

func loadTLSCredentials() (credentials.TransportCredentials, error) {
	serverCert, err := tls.LoadX509KeyPair("ssl/server-cert.pem", "ssl/server-key.pem")
	if err != nil {
		return nil, err
	}
	config := &tls.Config{
		Certificates: []tls.Certificate{serverCert},
		ClientAuth: tls.NoClientCert,
	}
	return credentials.NewTLS(config), nil
}
// main 函数中
tlsCredentials, err := loadTLSCredentials()
if err != nil {
	log.Fatalln("cannot load TLS credentials:", err)
}
grpcServer := grpc.NewServer(
	grpc.Creds(tlsCredentials),
	grpc.UnaryInterceptor(authInterceptor.Unary()),
	grpc.StreamInterceptor(authInterceptor.Stream()),
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

修改客户端启动函数:

func loadTLSCredentials() (credentials.TransportCredentials, error) {
	pemServerCA, err := ioutil.ReadFile("ssl/ca-cert.pem")
	if err != nil {
		return nil, err
	}
	certPool := x509.NewCertPool()
	if !certPool.AppendCertsFromPEM(pemServerCA) {
		return nil, fmt.Errorf("failed to add server CA's certificate")
	}
	config := &tls.Config{
		RootCAs: certPool,
	}
	return credentials.NewTLS(config), nil
}
tlsCredentials, err := loadTLSCredentials()
if err != nil {
	log.Fatalln("cannot load TLS credentials:", err)
}
conn, err := grpc.Dial(*serverAddress, grpc.WithTransportCredentials(tlsCredentials))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 双端认证

修改服务端启动函数:

func loadTLSCredentials() (credentials.TransportCredentials, error) {
	serverCert, err := tls.LoadX509KeyPair("ssl/server-cert.pem", "ssl/server-key.pem")
	if err != nil {
		return nil, err
	}
  // 这里添加 CA 相关。
	pemClientCA, err := ioutil.ReadFile("ssl/ca-cert.pem")
	if err != nil {
		return nil, err
	}
	certPool := x509.NewCertPool()
	if !certPool.AppendCertsFromPEM(pemClientCA) {
		return nil, fmt.Errorf("failed to add client CA's certificate")
	}
	config := &tls.Config{
    // 结构体内成员修改。
		Certificates: []tls.Certificate{serverCert},
		ClientAuth: tls.RequireAndVerifyClientCert,
		ClientCAs: certPool,
	}
	return credentials.NewTLS(config), nil
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

修改客户端启动函数:

func loadTLSCredentials() (credentials.TransportCredentials, error) {
	pemServerCA, err := ioutil.ReadFile("ssl/ca-cert.pem")
	if err != nil {
		return nil, err
	}
	certPool := x509.NewCertPool()
	if !certPool.AppendCertsFromPEM(pemServerCA) {
		return nil, fmt.Errorf("failed to add server CA's certificate")
	}
  // 修改,添加客户端证书、密钥。
	clientCert, err := tls.LoadX509KeyPair("ssl/client-cert.pem", "ssl/client-key.pem")
	if err != nil {
		return nil, err
	}
	config := &tls.Config{
    // 修改
		Certificates: []tls.Certificate{clientCert},
		RootCAs: certPool,
	}
	return credentials.NewTLS(config), nil
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21