Complete TLS Workflow in Golang Made Simple: Full Process Explained

Leapcell: The Best of Serverless Web Hosting Explanation of the TLS Handshake Process The TLS (Transport Layer Security) handshake is a vital procedure that enables secure communication between a client (such as a web browser) and a server (such as a web server). Below is a detailed breakdown of the entire TLS handshake process: Client Hello The client starts the handshake by sending a "Client Hello" message to the server. This message contains: The TLS versions supported by the client. A list of cipher suites (encryption algorithms) it supports. A random byte string (referred to as Client Random). Server Hello The server replies with a "Server Hello" message. This message includes: The selected TLS version. The chosen cipher suite. A random byte string (known as Server Random). The server's digital certificate (issued by a trusted Certificate Authority, CA). Certificate Verification The client verifies the server's certificate through the certificate authority (CA) chain. It ensures that the certificate is valid, not expired, and issued to the correct domain. Pre - Master Secret Generation The client generates a "Pre - Master Secret" using the server's public key (extracted from the certificate). This secret is encrypted and sent to the server. Master Secret Derivation Both the client and the server generate the "Master Secret" using the following: The Client Random. The Server Random. The Pre - Master Secret. The Master Secret is used to derive session keys for encryption and integrity checks. Session Keys Creation Using the Master Secret, both parties create: Encryption keys for symmetric encryption. MAC (Message Authentication Code) keys for integrity checks. Client Finished The client sends a "Finished" message, which is encrypted with the session keys. This confirms that the handshake was successful and that future messages will be encrypted. Server Finished The server sends its own "Finished" message, encrypted with the session keys. This marks the end of the handshake and the start of encrypted communication. Data Transfer All subsequent communication is encrypted using the derived session keys. Data is sent in encrypted packets with integrity checks. Diagram of the TLS Handshake Process +----------------------------------------+ +----------------------------------------+ | Client | | Server | +----------------------------------------+ +----------------------------------------+ | | | | | ClientHello |----->| | | [TLS Version, Cipher Suites, Random] | | | | | | | | | | ServerHello | | || | | [Start Using Encryption] | | | | | | | | Finished |----->| | | [Verifies Handshake Integrity] | | | | | | | | |

May 23, 2025 - 16:40
 0
Complete TLS Workflow in Golang Made Simple: Full Process Explained

Image description

Leapcell: The Best of Serverless Web Hosting

Explanation of the TLS Handshake Process

The TLS (Transport Layer Security) handshake is a vital procedure that enables secure communication between a client (such as a web browser) and a server (such as a web server). Below is a detailed breakdown of the entire TLS handshake process:

  1. Client Hello

    • The client starts the handshake by sending a "Client Hello" message to the server.
    • This message contains:
      • The TLS versions supported by the client.
      • A list of cipher suites (encryption algorithms) it supports.
      • A random byte string (referred to as Client Random).
  2. Server Hello

    • The server replies with a "Server Hello" message.
    • This message includes:
      • The selected TLS version.
      • The chosen cipher suite.
      • A random byte string (known as Server Random).
      • The server's digital certificate (issued by a trusted Certificate Authority, CA).
  3. Certificate Verification

    • The client verifies the server's certificate through the certificate authority (CA) chain.
    • It ensures that the certificate is valid, not expired, and issued to the correct domain.
  4. Pre - Master Secret Generation

    • The client generates a "Pre - Master Secret" using the server's public key (extracted from the certificate).
    • This secret is encrypted and sent to the server.
  5. Master Secret Derivation

    • Both the client and the server generate the "Master Secret" using the following:
      • The Client Random.
      • The Server Random.
      • The Pre - Master Secret.
    • The Master Secret is used to derive session keys for encryption and integrity checks.
  6. Session Keys Creation

    • Using the Master Secret, both parties create:
      • Encryption keys for symmetric encryption.
      • MAC (Message Authentication Code) keys for integrity checks.
  7. Client Finished

    • The client sends a "Finished" message, which is encrypted with the session keys.
    • This confirms that the handshake was successful and that future messages will be encrypted.
  8. Server Finished

    • The server sends its own "Finished" message, encrypted with the session keys.
    • This marks the end of the handshake and the start of encrypted communication.
  9. Data Transfer

    • All subsequent communication is encrypted using the derived session keys.
    • Data is sent in encrypted packets with integrity checks.

Diagram of the TLS Handshake Process

+----------------------------------------+      +----------------------------------------+
|               Client                   |      |               Server                   |
+----------------------------------------+      +----------------------------------------+
|                                        |      |                                        |
|  ClientHello                           |----->|                                        |
|  [TLS Version, Cipher Suites, Random]  |      |                                        |
|                                        |      |                                        |
|                                        |      |  ServerHello                            |
|                                        |<-----|  [TLS Version, Cipher Suite, Random]  |
|                                        |      |                                        |
|                                        |<-----|  Certificate                           |
|                                        |      |  [Server's Public Key]                 |
|                                        |      |                                        |
|                                        |<-----|  ServerHelloDone                       |
|                                        |      |                                        |
|  CertificateVerify                     |      |                                        |
|  [Verify Server's Certificate]         |      |                                        |
|                                        |      |                                        |
|  ClientKeyExchange                     |----->|                                        |
|  [Encrypted Pre-Master Secret]         |      |                                        |
|                                        |      |                                        |
|  ChangeCipherSpec                      |----->|                                        |
|  [Start Using Encryption]              |      |                                        |
|                                        |      |                                        |
|  Finished                              |----->|                                        |
|  [Verifies Handshake Integrity]        |      |                                        |
|                                        |      |                                        |
|                                        |<-----|  ChangeCipherSpec                      |
|                                        |      |  [Start Using Encryption]              |
|                                        |      |                                        |
|                                        |<-----|  Finished                              |
|                                        |      |  [Verifies Handshake Integrity]        |
|                                        |      |                                        |
|  Secure Communication                  |<--->|  Secure Communication                  |
|  [Encrypted Data Transfer]             |      |  [Encrypted Data Transfer]             |
+----------------------------------------+      +----------------------------------------+

Obtaining the TLS Client Hello Message with GoLang

Here's how to implement a server that captures all ClientHello messages using GoLang:

Certificate Generation

First, generate the necessary SSL certificates:

# Generate a private key
openssl genrsa -out server.key 2048
# Generate a public key (certificate)
openssl req -new -x509 -key server.key -out server.pem -days 3650

Server Implementation

The following is the complete server code for capturing ClientHello information:

package main

import (
    "bufio"
    "crypto/tls"
    "encoding/json"
    "fmt"
    "io/ioutil"
    "log"
    "net"
    "os"
    "sync"
    "time"
)

type CollectInfos struct {
    ClientHellos []*tls.ClientHelloInfo
    sync.Mutex
}

var collectInfos CollectInfos
var currentClientHello *tls.ClientHelloInfo

func (c *CollectInfos) collectClientHello(clientHello *tls.ClientHelloInfo) {
    c.Lock()
    defer c.Unlock()
    c.ClientHellos = append(c.ClientHellos, clientHello)
}

func (c *CollectInfos) DumpInfo() {
    c.Lock()
    defer c.Unlock()
    data, err := json.Marshal(c.ClientHellos)
    if err != nil {
        log.Fatal(err)
    }
    ioutil.WriteFile("hello.json", data, os.ModePerm)
}

func getCert() *tls.Certificate {
    cert, err := tls.LoadX509KeyPair("server.pem", "server.key")
    if err != nil {
        log.Println(err)
        return nil
    }
    return &cert
}

func buildTlsConfig(cert *tls.Certificate) *tls.Config {
    cfg := &tls.Config{
        Certificates: []tls.Certificate{*cert},
        GetConfigForClient: func(clientHello *tls.ClientHelloInfo) (*tls.Config, error) {
            collectInfos.collectClientHello(clientHello)
            currentClientHello = clientHello
            return nil, nil
        },
    }
    return cfg
}

func serve(cfg *tls.Config) {
    ln, err := tls.Listen("tcp", ":443", cfg)
    if err != nil {
        log.Println(err)
        return
    }
    defer ln.Close()
    for {
        conn, err := ln.Accept()
        if err != nil {
            log.Println(err)
            continue
        }
        go handler(conn)
    }
}

func handler(conn net.Conn) {
    defer conn.Close()
    r := bufio.NewReader(conn)
    for {
        msg, err := r.ReadString('\n')
        if err != nil {
            log.Println(err)
            return
        }
        fmt.Println(msg)
        data, err := json.Marshal(currentClientHello)
        if err != nil {
            log.Fatal(err)
        }
        _, err = conn.Write(data)
        if err != nil {
            log.Println(err)
            return
        }
    }
}

func main() {
    go func() {
        for {
            collectInfos.DumpInfo()
            time.Sleep(10 * time.Second)
        }
    }()
    cert := getCert()
    if cert != nil {
        serve(buildTlsConfig(cert))
    }
}

Client Implementation

The corresponding client code is as follows:

func main() {
    conn, err := tls.Dial("tcp", "localhost:443", &tls.Config{InsecureSkipVerify: true})
    if err != nil {
        log.Fatal(err)
    }
    defer conn.Close()
    _, err = conn.Write([]byte("hello\n"))
    if err != nil {
        log.Fatal(err)
    }
    buf := make([]byte, 1000)
    n, err := conn.Read(buf)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(string(buf[:n]))
}

This implementation enables you to capture detailed information from ClientHello messages during the TLS handshake process. The server periodically exports this information to a JSON file for analysis.

Leapcell: The Best of Serverless Web Hosting

Finally, recommend a platform that is most suitable for deploying Go services: Leapcell

Image description