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 errorEOF
on the client side - Using
https
for the client and changing some TLS versions but I got the errorremote error: tls: handshake failure
- Using TLS version 13, I got an error
remote error: tls: internal error
Related questions:
- Go https client issue - remote error: tls: handshake failure
- Golang http request results in EOF errors when making multiple requests successively
UPDATE:
- I log the handshake error from the
tls-ext
package and got an errorno cipher suite supported by both client and server