package main import ( "crypto/sha256" "crypto/tls" "crypto/x509" "encoding/hex" "errors" ) func tlsConfig() *tls.Config { return &tls.Config{ InsecureSkipVerify: true, VerifyConnection: tofuVerify, } } var tofuStore map[string]string var ErrTOFUViolation = errors.New("certificate for this domain has changed") func tofuVerify(connState tls.ConnectionState) error { certhash, err := hashCert(connState.PeerCertificates[0]) if err != nil { return err } expected, ok := tofuStore[connState.ServerName] if !ok { tofuStore[connState.ServerName] = certhash return saveTofuStore(tofuStore) } if certhash != expected { return ErrTOFUViolation } return nil } func hashCert(cert *x509.Certificate) (string, error) { pubkeybytes, err := x509.MarshalPKIXPublicKey(cert.PublicKey) if err != nil { return "", err } hash := sha256.Sum256(pubkeybytes) return hex.EncodeToString(hash[:]), nil }