-
-
Save wheelcomplex/183e478dea118eb5750442deb58ae2ce to your computer and use it in GitHub Desktop.
Golang: Demonstrate creating a CA Certificate, and Creating and Signing Certs with the CA
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment