golang grpc ssl

本文介绍了在无中央证书权威(CA)和有CA的场景下,如何使用OpenSSL生成和配置SSL/TLS证书进行客户端和服务器的身份验证。在无CA场景中,客户端和服务器分别持有对方的公钥进行单向或双向认证。而在有CA的场景中,CA用于签署证书,确保通信的安全性。文章详细展示了客户端和服务器的Go语言代码示例,演示了如何加载和使用证书进行认证。
摘要由CSDN通过智能技术生成
  1. 无CA场景
    在不考虑CA的场景下呢,client有client.key和client.crt,server有server.key和server.crt,生成方式可以如下:
$ openssl genrsa -out server.key 2048
$ openssl req -new -x509 -days 3650 \
    -subj "/C=GB/L=China/O=grpc-server/CN=server.grpc.io" \
    -key server.key -out server.crt

$ openssl genrsa -out client.key 2048
$ openssl req -new -x509 -days 3650 \
    -subj "/C=GB/L=China/O=grpc-client/CN=client.grpc.io" \
    -key client.key -out client.crt

key对应的是私钥,crt对应的是公钥

如果需要认证呢,首先, 认证分为单向认证和双向认证。
单向认证,client对server的认证,
双向认证,顾名思义是client和server相互认证

那么,对于client认证server来说,需要把server的公钥server.crt传给client,代码如下:

client

func main() {
    creds, err := credentials.NewClientTLSFromFile(
        "server.crt", "server.grpc.io",
    )
    if err != nil {
        log.Fatal(err)
    }

    conn, err := grpc.Dial("localhost:5000",
        grpc.WithTransportCredentials(creds),
    )
    if err != nil {
        log.Fatal(err)
    }
    defer conn.Close()

    ...
}

server

func main() {
    creds, err := credentials.NewServerTLSFromFile("server.crt", "server.key")
    if err != nil {
        log.Fatal(err)
    }

    server := grpc.NewServer(grpc.Creds(creds))

    ...
}

那么对于双向认证来说,不仅client需要校验server的公钥server.crt,server同样需要校验client的公钥client.crt

server

func main() {
    creds, err := credentials.NewServerTLSFromFile("server.crt", "server.key")
    if err != nil {
        log.Fatal(err)
    }

    server := grpc.NewServer(grpc.Creds(creds))

    ...
}

client

func main() {
    creds, err := credentials.NewClientTLSFromFile(
        "server.crt", "server.grpc.io",
    )
    if err != nil {
        log.Fatal(err)
    }

    conn, err := grpc.Dial("localhost:5000",
        grpc.WithTransportCredentials(creds),
    )
    if err != nil {
        log.Fatal(err)
    }
    defer conn.Close()

    ...
}
  1. 对于有Ca的场景,ca就是一个第三方认证机构,来保证

一般来说,ca的证书生成如下

生成ca私钥

 openssl genrsa -out ca.key 4096

生成CA证书

openssl req -new -x509 -days 365 -subj "/C=GB/L=Beijing/O=github/CN=liuqh.icu" \
-key ca.key -out ca.crt

这样我们就得到了一个ca.crt的ca证书

然后我们如何用ca证书对公钥进行签发呢?一般流程如下

以client端举例

生成私钥

openssl genrsa -out client.key

生成CSR

openssl req -new -subj "/C=GB/L=Beijing/O=github/CN=liuqh.icu"  \
-key client.key -out client.csr 

基于CA签发证书

openssl x509 -req -sha256 -CA ca.crt -CAkey ca.key -CAcreateserial -days 365 \
-in client.csr -out client.crt

其实这里感觉屏蔽了很多细节。首先我们要知道,基于ca签发证书,本质是通过ca的私钥加密生成了client公钥client.crt,如果server安装了ca.crt,则server就获得了ca的公钥,这样可以对ca签发的client.crt进行解密验证。反向是相同道理的。

那我们再分析几种场景的写法,首先单向认证,client验证server,那么client只需要ca.crt即可验证server了

client

func main() {
	// Load the server's CA certificate
	caCert, err := ioutil.ReadFile("ca.crt")
	if err != nil {
		log.Fatalf("failed to load CA certificate: %v", err)
	}
	caCertPool := x509.NewCertPool()
	if ok := caCertPool.AppendCertsFromPEM(caCert); !ok {
		log.Fatalf("failed to append CA certificate to the certificate pool")
	}

	// Create a new TLS configuration with the client's certificate and private key
	tlsConfig := &tls.Config{
		ServerName:   nodeConfigSsl.ServerName,
		RootCAs:      caCertPool,
	}

	// Create a new gRPC connection with the TLS transport credential
	clientCreds := credentials.NewTLS(tlsConfig)
	conn, err := grpc.Dial("localhost:12345", grpc.WithTransportCredentials(clientCreds))
	if err != nil {
	}

	// Create a new gRPC client with the connection
	client := NewGreeterClient(conn)
	
	// Send a gRPC request to the server
	resp, err := client.SayHello(context.Background(), &HelloRequest{Name: "Alice"})
	if err != nil {
		log.Fatalf("failed to send request: %v", err)
	}
	
	// Print the server's response
	fmt.Println(resp.Message)
}

server

func main() {
	// Load the server's certificate, private key, and CA certificate
	serverCert, err := tls.LoadX509KeyPair("server.crt", "server.key")
	if err != nil {
		log.Fatalf("failed to load server credentials: %v", err)
	}

	// Create a new TLS configuration with the server's certificate and private key
	tlsConfig := &tls.Config{
		Certificates: []tls.Certificate{serverCert},
	}

	// Create a new gRPC server with the TLS transport credential
	serverCreds := credentials.NewTLS(tlsConfig)
	server := grpc.NewServer(grpc.Creds(serverCreds))

	// Register the gRPC server
	RegisterGreeterServer(server, &greeterServer{})

	// Listen for incoming connections
	lis, err := net.Listen("tcp", ":12345")
	if err != nil {
		log.Fatalf("failed to listen: %v", err)
	}

	// Start the gRPC server
	if err := server.Serve(lis); err != nil {
		log.Fatalf("failed to serve: %v", err)
	}
}

第二种双向验证,则需要client传送公钥,但是同时也server也需要传送公钥

server

func main() {
	// Load the server's certificate, private key, and CA certificate
	serverCert, err := tls.LoadX509KeyPair("server.crt", "server.key")
	if err != nil {
		log.Fatalf("failed to load server credentials: %v", err)
	}
	caCert, err := ioutil.ReadFile("ca.crt")
	if err != nil {
		log.Fatalf("failed to load CA certificate: %v", err)
	}
	caCertPool := x509.NewCertPool()
	if ok := caCertPool.AppendCertsFromPEM(caCert); !ok {
		log.Fatalf("failed to append CA certificate to the certificate pool")
	}

	// Create a new TLS configuration with the server's certificate and private key
	tlsConfig := &tls.Config{
		Certificates: []tls.Certificate{serverCert},
		ClientAuth:   tls.RequireAndVerifyClientCert,
		ClientCAs:    caCertPool,
	}

	// Create a new gRPC server with the TLS transport credential
	serverCreds := credentials.NewTLS(tlsConfig)
	server := grpc.NewServer(grpc.Creds(serverCreds))

	// Register the gRPC server
	RegisterGreeterServer(server, &greeterServer{})

	// Listen for incoming connections
	lis, err := net.Listen("tcp", ":12345")
	if err != nil {
		log.Fatalf("failed to listen: %v", err)
	}

	// Start the gRPC server
	if err := server.Serve(lis); err != nil {
		log.Fatalf("failed to serve: %v", err)
	}
}

client

func main() {
	// Load the client's certificate and private key
	clientCert, err := tls.LoadX509KeyPair("client.crt", "client.key")
	if err != nil {
		log.Fatalf("failed to load client credentials: %v", err)
	}

	// Load the server's CA certificate
	caCert, err := ioutil.ReadFile("ca.crt")
	if err != nil {
		log.Fatalf("failed to load CA certificate: %v", err)
	}
	caCertPool := x509.NewCertPool()
	if ok := caCertPool.AppendCertsFromPEM(caCert); !ok {
		log.Fatalf("failed to append CA certificate to the certificate pool")
	}

	// Create a new TLS configuration with the client's certificate and private key
	tlsConfig := &tls.Config{
		Certificates: []tls.Certificate{clientCert},
		ServerName:   ServerName,
		RootCAs:      caCertPool,
	}

	// Create a new gRPC connection with the TLS transport credential
	clientCreds := credentials.NewTLS(tlsConfig)
	conn, err := grpc.Dial("localhost:12345", grpc.WithTransportCredentials(clientCreds))
	if err != nil {
	}

	// Create a new gRPC client with the connection
	client := NewGreeterClient(conn)
	
	// Send a gRPC request to the server
	resp, err := client.SayHello(context.Background(), &HelloRequest{Name: "Alice"})
	if err != nil {
		log.Fatalf("failed to send request: %v", err)
	}
	
	// Print the server's response
	fmt.Println(resp.Message)
	}

非常好的参考文章:
https://www.ruanyifeng.com/blog/2011/08/what_is_a_digital_signature.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值