Skip to content

08 Zinx TLS

刘丹冰 edited this page May 11, 2023 · 2 revisions

Case Source Code : https://github.com/aceld/zinx/tree/master/examples/zinx_tls

1. Sever

package main

import (
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/rand"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/pem"
	"github.com/aceld/zinx/zconf"
	"github.com/aceld/zinx/ziface"
	"github.com/aceld/zinx/zlog"
	"github.com/aceld/zinx/znet"
	"math/big"
	"os"
	"time"
)

// PingRouter is a custom router for ping test
type PingRouter struct {
	znet.BaseRouter
}

// Handle handles the ping request
func (this *PingRouter) Handle(request ziface.IRequest) {

	zlog.Debug("Call PingRouter Handle")
	// Read client data first, then write back ping...ping...ping
	zlog.Debug("Received from client: msgId=", request.GetMsgID(), ", data=", string(request.GetData()))

	err := request.GetConnection().SendBuffMsg(2, []byte("Pong with TLS"))
	if err != nil {
		zlog.Error(err)
	}
}

// genExampleCrtAndKeyFile generates certificate and key files for testing purposes only!! Please customize this function or use openssl to generate them for actual use.
// Refer to the following link for generating certificates and private keys using openssl: https://blog.csdn.net/qq_44637753/article/details/124152315
func genExampleCrtAndKeyFile(crtFileName, KeyFileName string) (err error) {
	// Regenerate if already exists
	_ = os.Remove(crtFileName)
	_ = os.Remove(KeyFileName)

	defer func() {
		if err != nil {
			// Remove the generated certificate and private key files if an error occurs during the process
			_ = os.Remove(crtFileName)
			_ = os.Remove(KeyFileName)
		}
	}()
	// Generate private key
	privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)

	// Create certificate template
	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
	if err != nil {
		return err
	}

	template := x509.Certificate{
		SerialNumber: serialNumber,
		Subject: pkix.Name{
			Organization: []string{"Beijing University of Post and Telecommunication"},
		},

		NotBefore: time.Now(),
		NotAfter:  time.Now().Add(24 * time.Hour * 365 * 10), // Certificate is valid for ten years

		KeyUsage:              x509.KeyUsageDigitalSignature,
		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
		BasicConstraintsValid: true,
	}

	// Create certificate
	derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &privateKey.PublicKey, privateKey)
	if err != nil {
		return err
	}

	// Serialize certificate file
	pemCert := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
	if pemCert == nil {
		return err
	}
	if err := os.WriteFile(crtFileName, pemCert, 0644); err != nil {
		return err
	}

	// Generate private key file
	privateBytes, err := x509.MarshalPKCS8PrivateKey(privateKey)
	if err != nil {
		return err
	}
	pemKey := pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: privateBytes})
	if pemKey == nil {
		return err
	}
	if err != nil {
            return err
        }
        if err := os.WriteFile(KeyFileName, pemKey, 0600); err != nil {
            return err
        }
        return nil
}

2. Client

package main

import (
	"fmt"
	"github.com/aceld/zinx/ziface"
	"github.com/aceld/zinx/zlog"
	"github.com/aceld/zinx/znet"
	"os"
	"os/signal"
	"time"
)

// PongRouter is a custom router for pong test
type PongRouter struct {
	znet.BaseRouter
}

// Handle is a method for handling the pong request
func (this *PongRouter) Handle(request ziface.IRequest) {

	zlog.Debug("Call PongRouter Handle")
	// Read data returned from the server
	zlog.Debug("recv from client : msgId=", request.GetMsgID(), ", data=", string(request.GetData()))
}

// Wait listens for interrupt and kill signals
func wait() {
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, os.Kill)
	sig := <-c
	fmt.Println("===exit===", sig)
}

func main() {
	// Create a TLS client
	c := znet.NewTLSClient("127.0.0.1", 8899)

	// Set up connection start function
	c.SetOnConnStart(func(connection ziface.IConnection) {
		go func() {
			for {
				// Send ping message
				err := connection.SendMsg(1, []byte("Ping with TLS"))

				if err != nil {
					fmt.Println(err)
					break
				}

				time.Sleep(1 * time.Second)
			}
		}()
	})

	// Add custom router
	c.AddRouter(2, &PongRouter{})

	// Start the client
	c.Start()

	// Wait for interrupt or kill signal
	wait()
}
Clone this wiki locally