@@ -0,0 +1,163 @@
package main
import (
"bytes"
"crypto/rand"
"crypto/rsa"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"fmt"
"io/ioutil"
"math/big"
"net"
"net/http"
"net/http/httptest"
"strings"
"time"
)
func main () {
// get our ca and server certificate
serverTLSConf , clientTLSConf , err := certsetup ()
if err != nil {
panic (err )
}
// set up the httptest.Server using our certificate signed by our CA
server := httptest .NewUnstartedServer (http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
fmt .Fprintln (w , "success!" )
}))
server .TLS = serverTLSConf
server .StartTLS ()
defer server .Close ()
// communicate with the server using an http.Client configured to trust our CA
transport := & http.Transport {
TLSClientConfig : clientTLSConf ,
}
http := http.Client {
Transport : transport ,
}
resp , err := http .Get (server .URL )
if err != nil {
panic (err )
}
// verify the response
respBodyBytes , err := ioutil .ReadAll (resp .Body )
if err != nil {
panic (err )
}
body := strings .TrimSpace (string (respBodyBytes [:]))
if body == "success!" {
fmt .Println (body )
} else {
panic ("not successful!" )
}
}
func certsetup () (serverTLSConf * tls.Config , clientTLSConf * tls.Config , err error ) {
// set up our CA certificate
ca := & x509.Certificate {
SerialNumber : big .NewInt (2019 ),
Subject : pkix.Name {
Organization : []string {"Company, INC." },
Country : []string {"US" },
Province : []string {"" },
Locality : []string {"San Francisco" },
StreetAddress : []string {"Golden Gate Bridge" },
PostalCode : []string {"94016" },
},
NotBefore : time .Now (),
NotAfter : time .Now ().AddDate (10 , 0 , 0 ),
IsCA : true ,
ExtKeyUsage : []x509.ExtKeyUsage {x509 .ExtKeyUsageClientAuth , x509 .ExtKeyUsageServerAuth },
KeyUsage : x509 .KeyUsageDigitalSignature | x509 .KeyUsageCertSign ,
BasicConstraintsValid : true ,
}
// create our private and public key
caPrivKey , err := rsa .GenerateKey (rand .Reader , 4096 )
if err != nil {
return nil , nil , err
}
// create the CA
caBytes , err := x509 .CreateCertificate (rand .Reader , ca , ca , & caPrivKey .PublicKey , caPrivKey )
if err != nil {
return nil , nil , err
}
// pem encode
caPEM := new (bytes.Buffer )
pem .Encode (caPEM , & pem.Block {
Type : "CERTIFICATE" ,
Bytes : caBytes ,
})
caPrivKeyPEM := new (bytes.Buffer )
pem .Encode (caPrivKeyPEM , & pem.Block {
Type : "RSA PRIVATE KEY" ,
Bytes : x509 .MarshalPKCS1PrivateKey (caPrivKey ),
})
// set up our server certificate
cert := & x509.Certificate {
SerialNumber : big .NewInt (2019 ),
Subject : pkix.Name {
Organization : []string {"Company, INC." },
Country : []string {"US" },
Province : []string {"" },
Locality : []string {"San Francisco" },
StreetAddress : []string {"Golden Gate Bridge" },
PostalCode : []string {"94016" },
},
IPAddresses : []net.IP {net .IPv4 (127 , 0 , 0 , 1 ), net .IPv6loopback },
NotBefore : time .Now (),
NotAfter : time .Now ().AddDate (10 , 0 , 0 ),
SubjectKeyId : []byte {1 , 2 , 3 , 4 , 6 },
ExtKeyUsage : []x509.ExtKeyUsage {x509 .ExtKeyUsageClientAuth , x509 .ExtKeyUsageServerAuth },
KeyUsage : x509 .KeyUsageDigitalSignature ,
}
certPrivKey , err := rsa .GenerateKey (rand .Reader , 4096 )
if err != nil {
return nil , nil , err
}
certBytes , err := x509 .CreateCertificate (rand .Reader , cert , ca , & certPrivKey .PublicKey , caPrivKey )
if err != nil {
return nil , nil , err
}
certPEM := new (bytes.Buffer )
pem .Encode (certPEM , & pem.Block {
Type : "CERTIFICATE" ,
Bytes : certBytes ,
})
certPrivKeyPEM := new (bytes.Buffer )
pem .Encode (certPrivKeyPEM , & pem.Block {
Type : "RSA PRIVATE KEY" ,
Bytes : x509 .MarshalPKCS1PrivateKey (certPrivKey ),
})
serverCert , err := tls .X509KeyPair (certPEM .Bytes (), certPrivKeyPEM .Bytes ())
if err != nil {
return nil , nil , err
}
serverTLSConf = & tls.Config {
Certificates : []tls.Certificate {serverCert },
}
certpool := x509 .NewCertPool ()
certpool .AppendCertsFromPEM (caPEM .Bytes ())
clientTLSConf = & tls.Config {
RootCAs : certpool ,
}
return
}