I am trying around with mTls and go. I do not really understand how I got tls errors during the handshake on the client side. See the following example:
package main
import (
"crypto/tls"
"crypto/x509"
"fmt"
"strconv"
"sync"
)
const CRT = "-----BEGIN CERTIFICATE-----\nMIIDHzCCAgegAwIBAgIGAYbbjzNfMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNVBAMM\nCTEyNy4wLjAuMTAeFw0yMzAzMTMxNTIwNDBaFw0yNDAzMTMxNTIwNDBaMBQxEjAQ\nBgNVBAMMCTEyNy4wLjAuMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\nAIlfhPzb31DD3ntWPLU2HSqb0z0dkns5hNQt3EN907wT2H+wnhPu9W21nOrQNk6D\nRPfs+2qzpuzMzbC1AAEz/YFrgctUgc7IDlMWOhmKusROb/VA4596jtIQpu35gUnO\niZ16V4ufUEGMn2ZNOB1FTlp+vTOjDvcEgXyEvwTrHjBAKf7/h8Ab8yQrEMZJLjNy\nUrC8IBtUKGr0qcYSBnbT35Y6weT0prZUi21trBQNtQQtegKnN3AssZnkUar3oc1M\nPSfEO385QbTj5P0RV6lYCdNNzlzZiyf89qdK1GwqjWIC5NMEfhgCWBmdwo4SHUUo\nPELmFekxNF1CC1fqARHke/ECAwEAAaN3MHUwDwYDVR0TAQH/BAUwAwEB/zAfBgNV\nHSMEGDAWgBQFgC5rEruxtIhgyck1mfJWlgnYVzAdBgNVHQ4EFgQUBYAuaxK7sbSI\nYMnJNZnyVpYJ2FcwDgYDVR0PAQH/BAQDAgGGMBIGA1UdEQEB/wQIMAaHBH8AAAEw\nDQYJKoZIhvcNAQELBQADggEBAHPFf7OJxMHuc7NpIR/qY9gWVyICwsDVN/V92ZDm\ng4IVhiQSyTYmtjQwbN848WRtihw3aR4FX1nvaDggHoHgdH2ug1pcdUUV4CjGTqaH\nCH5IRkg7SrlC2GimPS1LKGlB9a+nruFMevPez1Cn5OyFJ87mjcVsg+iHdhOXJD6M\ng3aN+UuslneYeLhmnupjJw4c7hZtQM8TfiuZ5ck+nGMupDXFZo5iBCS+fx9l8e3b\ntJUsmov2OmEDC+7lqkds4nBAj7GCvaD7vJr2bmwj3tNY1VURugQSIhuzWTAxohry\nM+GhLnsX+JNAU2e8E9cxCcceC8IaPAbX8y1teGCt9ukIxhE=\n-----END CERTIFICATE-----\n"
const KEY = "-----BEGIN RSA PRIVATE KEY-----\nMIIEogIBAAKCAQEAiV+E/NvfUMPee1Y8tTYdKpvTPR2SezmE1C3cQ33TvBPYf7Ce\nE+71bbWc6tA2ToNE9+z7arOm7MzNsLUAATP9gWuBy1SBzsgOUxY6GYq6xE5v9UDj\nn3qO0hCm7fmBSc6JnXpXi59QQYyfZk04HUVOWn69M6MO9wSBfIS/BOseMEAp/v+H\nwBvzJCsQxkkuM3JSsLwgG1QoavSpxhIGdtPfljrB5PSmtlSLbW2sFA21BC16Aqc3\ncCyxmeRRqvehzUw9J8Q7fzlBtOPk/RFXqVgJ003OXNmLJ/z2p0rUbCqNYgLk0wR+\nGAJYGZ3CjhIdRSg8QuYV6TE0XUILV+oBEeR78QIDAQABAoIBACYEJaD2VgwbUGAQ\ngvdhFNw8SE6S9v0b81rmoBybXzOeyFy561031Xq5dkXzPfwnTrhPwFoMgobovImI\n5YnvsdmVf1NePRgU/AXZUlXMMxhtXoVgIj35pDmU+yVDVZivzBylBUIx4ftp55jf\niMZs7hyUE1cNanBIsm7bq6M4T9/pEf41Ayf0XgkMOkjn2RpZCTdwvDASw2L0hzVv\nf9lZow1LecARdwD8dMvQ0oI7P4hSCzfTCi6JLioxLuu+8yw20Rn9/r2xV2UErPhe\nxhgxAUBLwVMlArb1c+ZVXFZpx+e1tmwmqTeAKptmFQNQkljwAEQB+6GEKhV01sQ9\nCG94SlMCgYEAwWMqdGX/KkXcCkjLbuu7qMspbI9zwoXdKc2eqp5sS6jex/gzS/Y6\nx0yMTq3wUIbHfDcVlRu9cmadW483I7DZCnRX7R0GFcW6YKA/Uog+8nykd5zA/aG8\na5tALJEd3JRNihHchxHwYpQEdklzfksN/i20CxRTehlyAQMs+jJBEz8CgYEAtdmi\ntR6YbwwxhRn7/kX/H39sEsb00sFRbSCTv8TR6nuBfmjISLY949PJ4TELj7PW7vgT\n1Rut6lsR7dSyqv6+p0J6pNfu90BUni+HRDtQyI60qiMhXqfHxpEUofkK6/er0yxN\no+Wp0NQa0788rGhNR7deTGrvQAwAl+tX2MX7FM8CgYBhrMGLqtyXMFO0ChJeAsh0\nt7BDea0BKfWLoKQsDvopuLBVFeJq0oHbmakgMDA5q+ljrrrC5hDokDWYQhyadT8a\nTar/QvKI2qaJGUcCW3hXp2a2V0EOmbr+KpreJ6mKeIk1XFIjEod0cshSKkUgG66E\nm/bcxbZn7CQtqLn14J4HpwKBgDIqQn9SXFyt8W81VtWzO4jV3ttjNSB6odrH1Npf\nEkVsIrHbd/zPAU27HALaQ8U1qEIt/1KXmyd+Tfjc5xjSw4diiHC2/L4Kag1lMRx6\nfHOHIoGYxVjWUf8OALIaAJBNt4G+xABFl8365ReqtrMc5sy04feUvEFfzj4adxZe\nrz/zAoGAU502B+/HvgdodBzdw2iQJseEG1eNaUoA1co2OxHUHlaPukt5RjOwuXrP\nobVdqbtBb9aa4ZbRl9Y1yvllJMTSzrWvWra1eV3czQOVS34FwaJ06AzaUCR7ht7D\nVOObYItn69ougXDjKwHR9t/q02fLVMmUAYBKEqaVWErMzJnssrQ=\n-----END RSA PRIVATE KEY-----\n"
const PORT = 1555
var wg sync.WaitGroup
func main() {
startServer()
config := &tls.Config{
RootCAs: x509.NewCertPool(),
}
config.RootCAs.AppendCertsFromPEM([]byte(CRT))
con, err := tls.Dial("tcp", "127.0.0.1:"+strconv.Itoa(1555), config)
if err != nil {
fmt.Println("I do not have a client cert, I should reach here")
panic(err)
}
defer con.Close()
n, err := con.Write([]byte("msg"))
if err != nil {
fmt.Println("At least here should be a error")
panic(err)
}
fmt.Printf("Wrote %d bytes\n", n)
wg.Wait()
}
func startServer() {
wg.Add(1)
cert, _ := tls.X509KeyPair([]byte(CRT), []byte(KEY))
config := &tls.Config{
Certificates: []tls.Certificate{cert},
ClientAuth: tls.RequireAndVerifyClientCert,
ClientCAs: x509.NewCertPool(),
}
config.ClientCAs.AppendCertsFromPEM([]byte(CRT))
socket, _ := tls.Listen("tcp", ":"+strconv.Itoa(PORT), config)
buffer := make([]byte, 1024)
go func() {
defer wg.Done()
defer socket.Close()
conn, _ := socket.Accept()
n, _ := conn.Read(buffer)
fmt.Println(string(buffer[:n]))
conn.Close()
}()
}
The Server is configured with RequireAndVerifyClientCert
. If you run this example you will also see that on the server side the string msg
is not printed. This I am expecting since I do not send a client certificate. But the client says the message was transmitted successful.
The strange part is, I would expect that a I got an error during the tls.Dial
call on the client side. But maybe this is just the tcp connection and tls will be done later.
But the really strange part is, that i can call the write function and this does not return an error and even returns n=3
indecating that the server received 3 bytes.
Note: If you change RequireAndVerifyClientCert
to NoClientCert
the server part will correctly receive the message.
Why does go not tell me that the tls handshake has failed? Or does it really not fail (What am I doing wrong)?