1

I am learning how to use TLS-PSK in an HTTP connection with the Go programming language. I have used these two packages:

and follow the example here but still I couldn't make it.

My server code:

...

type M map[string]interface{}

func main() {
    mux := new(http.ServeMux)
    mux.HandleFunc("/data", ActionData)

    s := &http.Server{
        Addr:    ":9080",
        Handler: mux,
    }

    cfg := &tls.Config{
        CipherSuites: []uint16{psk.TLS_DHE_PSK_WITH_AES_128_CBC_SHA, psk.TLS_DHE_PSK_WITH_AES_256_CBC_SHA},
        Certificates: []tls.Certificate{{}},
        MaxVersion:   tls.VersionTLS11,
        MinVersion:   tls.VersionTLS13,
        Extra: psk.PSKConfig{
            GetKey: func(identity string) ([]byte, error) {
                hexString := "166ACC41EC1D4E1DD001ECC130ED0810"
                key := make([]byte, hex.DecodedLen(len(hexString)))
                _, err := hex.Decode(key, []byte(hexString))
                if err != nil {
                    return nil, err
                }
                return key, nil
            },
        },
    }

    l, err := net.Listen("tcp", ":9080")

    if err != nil {
        log.Fatalln("Failed to start web server", err)
    }

    l = tls.NewListener(l, cfg)

    log.Println("Starting server at 9080")
    if err := s.Serve(l); err != nil {
        log.Fatalln("error starting server:", err)
    }

}

func ActionData(w http.ResponseWriter, r *http.Request) {
    log.Println("Incoming request with method", r.Method)

    if r.Method != "POST" {
        http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
        return
    }

    payload := make(M)
    err := json.NewDecoder(r.Body).Decode(&payload)
    if err != nil {
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }

    if _, ok := payload["Name"]; !ok {
        http.Error(w, "Payload `Name` is required", http.StatusBadRequest)
        return
    }

    data := M{
        "Message": fmt.Sprintf("Hello %s", payload["Name"]),
        "Status":  true,
    }

    w.Header().Set("Content-Type", "application/json")
    err = json.NewEncoder(w).Encode(data)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
    }
}

My client code:

...
type M map[string]interface{}

var (
    Config = &tls.Config{
        // ServerName: "client-PSK-test",
        PreferServerCipherSuites: true,
        InsecureSkipVerify:       true,
        CipherSuites:             []uint16{psk.TLS_PSK_WITH_AES_128_CBC_SHA},
        Certificates:             []tls.Certificate{{}},
        Extra: psk.PSKConfig{
            GetIdentity: func() string {
                return "123"
            },
            GetKey: func(identity string) ([]byte, error) {
                hexString := "166ACC41EC1D4E1DD001ECC130ED0810"
                key := make([]byte, hex.DecodedLen(len(hexString)))
                _, err := hex.Decode(key, []byte(hexString))
                if err != nil {
                    return nil, err
                }
                return key, nil
            },
        },
    }
)

func main() {
    baseURL := "http://localhost:9080"
    data := M{"Name": "Noval Agung"}

    responseBody, err := doRequest(baseURL+"/data", "POST", data)
    if err != nil {
        log.Println("ERROR: do request:", err.Error())
        return
    }

    log.Printf("%#v \n", responseBody)
}

func doRequest(url, method string, data interface{}) (interface{}, error) {
    var payload *bytes.Buffer = nil

    if data != nil {
        payload = new(bytes.Buffer)
        err := json.NewEncoder(payload).Encode(data)
        if err != nil {
            return nil, fmt.Errorf("error json encoding: %v", err)
        }
    }

    request, err := http.NewRequest(method, url, payload)
    if err != nil {
        return nil, fmt.Errorf("error creating new request: %v", err)
    }
    request.Header.Set("Content-Type", "application/json")

    client := &http.Client{

        Transport: &http.Transport{
            DialTLS: func(network, addr string) (net.Conn, error) {
                return tls.Dial(network, addr, Config)
            },
        },
    }

    response, err := client.Do(request)
    if err != nil {
        return nil, fmt.Errorf("error client.Do(): %v", err)
    }
    if response != nil {
        defer response.Body.Close()
    }

    responseBody := make(M)
    err = json.NewDecoder(response.Body).Decode(&responseBody)
    if err != nil {
        return nil, err
    }

    return responseBody, nil
}

Some measures that I ever tried:

  • Using http for the client but I got the error EOF on the client side
  • Using https for the client and changing some TLS versions but I got the error remote error: tls: handshake failure
  • Using TLS version 13, I got an error remote error: tls: internal error

Related questions:

UPDATE:

  • I log the handshake error from the tls-ext package and got an error no cipher suite supported by both client and server
A.Y. Wicaksono
  • 161
  • 1
  • 10

0 Answers0