I need to connect client & server over untrusted network. I've considered using TLS (crypto/tls), but from what I understand, I first need to create a create a crypto/x509.Certificate. But I feel overwhelmed by all the parameters I need to pass to the x509.CreateCertificate() function - it says it needs all of the following fields:
SerialNumber, Subject, NotBefore, NotAfter, KeyUsage, BasicConstraintsValid, IsCA, MaxPathLen, SubjectKeyId, DNSNames, PermittedDNSDomainsCritical, PermittedDNSDomains.
I have full control over both endpoints, so I believe I don't need any expiration or invalidation support/parameters (I can change keys both on client and server at any time I want) - so I can probably skip NotBefore and NotAfter (? or do I have to set them anyway?). What should I put in all the other fields, and why, to avoid any vulnerabilities? Also, can I use the same private/public key pair for both ways authentication (client to server, and server to client), or do I have to use 2 pairs?
Or, is there something simpler than TLS that I could use? Note however, that I need to two way authentication.
EDIT:
I created a simple library based on suggestions from the accepted answer, plus key generation code from generate_cert.go - see:
github.com/akavel/tunnel
Owlstead is partly correct. Your best bet is creating self signed certificates using OpenSSL. However, I would then use the Go TLS library for encryption. Below is some code that may help you.
I normally follow the instructions here. Summary of commands (do for both client and server):
openssl genrsa -des3 -out server.key 1024
openssl req -new -key server.key -out server.csr
cp server.key server.key.org
openssl rsa -in server.key.org -out server.key
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
First, create a tls.Config
. One TLS config will work on both client and server but some of the options only need to be set on one or the other:
cert, err := tls.LoadX509KeyPair(cert, key)
config := &tls.Config{
Certificates: []Certificates{cert},
ClientAuth: tls.RequireAnyClientCert, // Must be done on server
InsecureSkipVerify: true, // Must be done on client
}
On the server, you need to setup a TLS listener. This sets it up on port 4443:
listener, err := tls.Listen("tcp", ":4443", config)
for {
conn, err := listener.Accept()
acceptConn(conn) // your code
}
On the client:
conn, err := tls.Dial("tcp", serverAddr, config)
This will create an encrypted connection, but it will not verify the other side is who they say they are. The easiest way to do that is to give each server the public key of the other server and compare it to the server that has just connected. To find the public key on the other server, you need to:
c := conn.(*tls.Conn) // convert net.Conn from listener to tls conn
err := c.Handshake() // ensure handshake is completed without error
state := c.ConnectionState()
pubKey, err := x509.MarshalPKIXPublicKey(state.PeerCertificates[0])
bytes.Equal(pubKey, knownKey) // compare to known value
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With