Skip to content

Instantly share code, notes, and snippets.

@cromefire
Last active August 10, 2019 11:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cromefire/590eb9743dbadeca89c213b0aa1a2d58 to your computer and use it in GitHub Desktop.
Save cromefire/590eb9743dbadeca89c213b0aa1a2d58 to your computer and use it in GitHub Desktop.
go client cert error
package main
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/rsa"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"fmt"
"math/big"
"net/http"
"os"
"time"
)
func publicKey(priv interface{}) interface{} {
switch k := priv.(type) {
case *rsa.PrivateKey:
return &k.PublicKey
case *ecdsa.PrivateKey:
return &k.PublicKey
default:
return nil
}
}
func pemBlockForKey(priv interface{}) (*pem.Block, error) {
switch k := priv.(type) {
case *rsa.PrivateKey:
return &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(k)}, nil
case *ecdsa.PrivateKey:
b, err := x509.MarshalECPrivateKey(k)
if err != nil {
return nil, err
}
return &pem.Block{Type: "EC PRIVATE KEY", Bytes: b}, nil
default:
return nil, fmt.Errorf("unknown key type")
}
}
// NewCertificateEcc generates and returns a new TLS certificate.
func NewCertificateEcc(commonName string) (tls.Certificate, error) {
priv, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
if err != nil {
return tls.Certificate{}, fmt.Errorf("generate key: %s", err)
}
notBefore := time.Now()
notAfter := time.Date(2049, 12, 31, 23, 59, 59, 0, time.UTC)
template := x509.Certificate{
SerialNumber: new(big.Int).SetInt64(123912838),
Subject: pkix.Name{
CommonName: commonName,
},
NotBefore: notBefore,
NotAfter: notAfter,
SignatureAlgorithm: x509.ECDSAWithSHA256,
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
BasicConstraintsValid: true,
}
derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, publicKey(priv), priv)
if err != nil {
return tls.Certificate{}, fmt.Errorf("create cert: %s", err)
}
certFile := "ecccert.pem"
certOut, err := os.Create(certFile)
if err != nil {
return tls.Certificate{}, fmt.Errorf("save cert: %s", err)
}
err = pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
if err != nil {
return tls.Certificate{}, fmt.Errorf("save cert: %s", err)
}
err = certOut.Close()
if err != nil {
return tls.Certificate{}, fmt.Errorf("save cert: %s", err)
}
keyFile := "ecckey.pem"
keyOut, err := os.OpenFile(keyFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
return tls.Certificate{}, fmt.Errorf("save key: %s", err)
}
block, err := pemBlockForKey(priv)
if err != nil {
return tls.Certificate{}, fmt.Errorf("save key: %s", err)
}
err = pem.Encode(keyOut, block)
if err != nil {
return tls.Certificate{}, fmt.Errorf("save key: %s", err)
}
err = keyOut.Close()
if err != nil {
return tls.Certificate{}, fmt.Errorf("save key: %s", err)
}
return tls.LoadX509KeyPair(certFile, keyFile)
}
// NewCertificateRsa generates and returns a new TLS certificate.
func NewCertificateRsa(commonName string) (tls.Certificate, error) {
priv, err := rsa.GenerateKey(rand.Reader, 4092)
if err != nil {
return tls.Certificate{}, fmt.Errorf("generate key: %s", err)
}
notBefore := time.Now()
notAfter := time.Date(2049, 12, 31, 23, 59, 59, 0, time.UTC)
template := x509.Certificate{
SerialNumber: new(big.Int).SetInt64(123912838),
Subject: pkix.Name{
CommonName: commonName,
},
NotBefore: notBefore,
NotAfter: notAfter,
SignatureAlgorithm: x509.SHA384WithRSA,
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
BasicConstraintsValid: true,
}
derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, publicKey(priv), priv)
if err != nil {
return tls.Certificate{}, fmt.Errorf("create cert: %s", err)
}
certFile := "rsacert.pem"
certOut, err := os.Create(certFile)
if err != nil {
return tls.Certificate{}, fmt.Errorf("save cert: %s", err)
}
err = pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
if err != nil {
return tls.Certificate{}, fmt.Errorf("save cert: %s", err)
}
err = certOut.Close()
if err != nil {
return tls.Certificate{}, fmt.Errorf("save cert: %s", err)
}
keyFile := "rsakey.pem"
keyOut, err := os.OpenFile(keyFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
return tls.Certificate{}, fmt.Errorf("save key: %s", err)
}
block, err := pemBlockForKey(priv)
if err != nil {
return tls.Certificate{}, fmt.Errorf("save key: %s", err)
}
err = pem.Encode(keyOut, block)
if err != nil {
return tls.Certificate{}, fmt.Errorf("save key: %s", err)
}
err = keyOut.Close()
if err != nil {
return tls.Certificate{}, fmt.Errorf("save key: %s", err)
}
return tls.LoadX509KeyPair(certFile, keyFile)
}
func main() {
kl, err := os.OpenFile("/tmp/keylog.txt", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
fmt.Printf("log: %s", err)
os.Exit(1)
}
_, err = fmt.Fprintf(kl, "# SSL/TLS secrets log file, generated by go\n")
if err != nil {
fmt.Printf("log: %s", err)
os.Exit(1)
}
fmt.Printf("Leaking TLS keys to /tmp/keylog.txt\n")
certEcc, err := NewCertificateEcc("test-client")
if err != nil {
fmt.Printf("client: %s", err)
os.Exit(1)
}
certRsa, err := NewCertificateRsa("test-client")
if err != nil {
fmt.Printf("client: %s", err)
os.Exit(1)
}
var rsaClient = &http.Client{
Timeout: 5 * time.Minute,
Transport: &http.Transport{
Proxy: http.ProxyFromEnvironment,
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
Certificates: []tls.Certificate{certRsa},
KeyLogWriter: kl,
},
},
}
var eccClient = &http.Client{
Timeout: 5 * time.Minute,
Transport: &http.Transport{
Proxy: http.ProxyFromEnvironment,
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
Certificates: []tls.Certificate{certEcc},
KeyLogWriter: kl,
},
},
}
var normalClient = &http.Client{
Timeout: 5 * time.Minute,
Transport: &http.Transport{
Proxy: http.ProxyFromEnvironment,
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
KeyLogWriter: kl,
},
},
}
_, err = rsaClient.Get("https://discovery.syncthing.net")
if err != nil {
fmt.Printf("rsa-ecc: %s\n", err)
} else {
fmt.Printf("rsa-ecc: ok\n")
}
_, err = eccClient.Get("https://discovery.syncthing.net")
if err != nil {
fmt.Printf("ecc-ecc: %s\n", err)
} else {
fmt.Printf("ecc-ecc: ok\n")
}
_, err = normalClient.Get("https://discovery.syncthing.net")
if err != nil {
fmt.Printf("nocert-ecc: %s\n", err)
} else {
fmt.Printf("nocert-ecc: ok\n")
}
_, err = rsaClient.Get("https://go-issue.cromefire.myds.me")
if err != nil {
fmt.Printf("rsa-rsa: %s\n", err)
} else {
fmt.Printf("rsa-rsa: ok\n")
}
_, err = eccClient.Get("https://go-issue.cromefire.myds.me")
if err != nil {
fmt.Printf("ecc-rsa: %s\n", err)
} else {
fmt.Printf("ecc-rsa: ok\n")
}
_, err = normalClient.Get("https://go-issue.cromefire.myds.me")
if err != nil {
fmt.Printf("nocert-rsa: %s\n", err)
} else {
fmt.Printf("nocert-rsa: ok\n")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment