Go certificate example 1

From UVOO Tech Wiki
Jump to navigation Jump to search

https://gist.github.com/shaneutt/5e1995295cff6721c89a71d13a71c251

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
}