Skip to content

Instantly share code, notes, and snippets.

@LivingInSyn
Created March 12, 2019 15:24
Show Gist options
  • Save LivingInSyn/f7d29b1c241db82694aff77a47a85930 to your computer and use it in GitHub Desktop.
Save LivingInSyn/f7d29b1c241db82694aff77a47a85930 to your computer and use it in GitHub Desktop.
package main
import (
"crypto/tls"
"crypto/x509"
"errors"
"io/ioutil"
"log"
"time"
)
var clientCert = "..\\..\\keys_and_certs\\client\\client_chain.crt"
var clientKey = "..\\..\\keys_and_certs\\client\\client.key"
var caPath = "..\\..\\keys_and_certs\\ca.crt"
func main() {
cer, err := tls.LoadX509KeyPair(clientCert, clientKey)
if err != nil {
log.Fatal(err)
}
conf := &tls.Config{
RootCAs: ConfigureRootCAs(&caPath),
Certificates: []tls.Certificate{cer},
MinVersion: tls.VersionTLS12,
//Turn on InsecureSkipVerify
InsecureSkipVerify: true,
//MUST TURN ON verify peer certificate (requires Go 1.8+)
VerifyPeerCertificate: ValidateCANotHostname,
}
conn, err := tls.Dial("tcp", "127.0.0.1:8443", conf)
if err != nil {
log.Println(err)
return
}
defer conn.Close()
n, err := conn.Write([]byte("hello\n"))
if err != nil {
log.Println(n, err)
return
}
buf := make([]byte, 100)
n, err = conn.Read(buf)
if err != nil {
log.Println(n, err)
return
}
println(string(buf[:n]))
}
// ValidateCANotHostname comes from https://github.com/golang/go/blob/39e523792e33a0bd9217161ca53c6c0cb2324a99/src/crypto/tls/handshake_client.go#L315-L344
// it is stripped from the source. We have to do this to remove DNSName from the VerifyOptions
func ValidateCANotHostname(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
//parse certificates
certs := make([]*x509.Certificate, len(rawCerts))
for i, asn1Data := range rawCerts {
cert, err := x509.ParseCertificate(asn1Data)
if err != nil {
return errors.New("tls: failed to parse certificate from server: " + err.Error())
}
certs[i] = cert
}
opts := x509.VerifyOptions{
Roots: ConfigureRootCAs(&caPath),
CurrentTime: time.Now(),
//DNSName: c.config.ServerName,
Intermediates: x509.NewCertPool(),
}
for i, cert := range certs {
if i == 0 {
continue
}
opts.Intermediates.AddCert(cert)
}
_, err := certs[0].Verify(opts)
if err != nil {
return err
}
return nil
}
//ConfigureRootCAs loads the CA from a file
func ConfigureRootCAs(caCertPathFlag *string) *x509.CertPool {
// also load as bytes for x509
// Read in the cert file
x509certs, err := ioutil.ReadFile(*caCertPathFlag)
if err != nil {
log.Fatalf("Failed to append certificate to RootCAs: %v", err)
}
//create the new cert file
rootCAs := x509.NewCertPool()
// append the local cert to the in-memory system CA pool
if ok := rootCAs.AppendCertsFromPEM(x509certs); !ok {
log.Panic("Couldn't load the Root CA")
}
return rootCAs
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment