Skip to content

Instantly share code, notes, and snippets.

@hectorcorrea
Last active October 10, 2017 17:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save hectorcorrea/9da7dd517953a353f6b2df7b47343e69 to your computer and use it in GitHub Desktop.
Save hectorcorrea/9da7dd517953a353f6b2df7b47343e69 to your computer and use it in GitHub Desktop.
An example on how to generate a local SSL certificate in Go and serve HTTPS traffic with it
// An example on how to generate a local SSL certificate in Go
// and serve HTTPS traffic with it.
//
// Code taken from the book Go Web Programming by Sau Sheong Chang
// https://github.com/sausheong/gwp
//
// Run with `--https` to serve traffic via HTTPS (it will create the certificate
// and private key files if they don't exist)
//
// Run with no parameters to serve traffic via HTTP (no certificates needed)
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"flag"
"fmt"
"log"
"math/big"
"net"
"net/http"
"os"
"time"
)
type MyHandler struct{}
func main() {
var https = flag.Bool("https", false, "true to server traffic via HTTPS")
flag.Parse()
startServer(*https)
}
func (h *MyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
now := time.Now()
fmt.Fprintf(w, "Hello World at %s", now)
log.Printf("%s %s", now, r.URL.Path)
}
func startServer(ssl bool) {
handler := MyHandler{}
server := http.Server{
Addr: "127.0.0.1:8080",
Handler: &handler,
}
if ssl {
generateCertificates()
log.Printf("Listening on https://%s", server.Addr)
server.ListenAndServeTLS("cert.pem", "key.pem")
} else {
log.Printf("Listening on http://%s", server.Addr)
server.ListenAndServe()
}
}
// Source: https://stackoverflow.com/a/10510783/446681
func fileExists(path string) bool {
_, err := os.Stat(path)
if err == nil {
return true
}
if os.IsNotExist(err) {
return false
}
return true
}
func generateCertificates() {
certFile := "cert.pem"
privateKeyFile := "key.pem"
if fileExists(certFile) && fileExists(privateKeyFile) {
return
}
max := new(big.Int).Lsh(big.NewInt(1), 128)
serialNumber, _ := rand.Int(rand.Reader, max)
subject := pkix.Name{
Organization: []string{"Hector"},
OrganizationalUnit: []string{"testing"},
CommonName: "Hector was here",
}
template := x509.Certificate{
SerialNumber: serialNumber,
Subject: subject,
NotBefore: time.Now(),
NotAfter: time.Now().Add(365 * 24 * time.Hour),
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
IPAddresses: []net.IP{net.ParseIP("127.0.0.1")},
}
pk, _ := rsa.GenerateKey(rand.Reader, 2048)
// Generate a private key. This is equivalent to running:
// openssl genrsa -out key.pem 2048
keyOut, _ := os.Create(privateKeyFile)
pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY",
Bytes: x509.MarshalPKCS1PrivateKey(pk)})
keyOut.Close()
log.Printf("Generated file key.pem (your private key)")
// Generate a self-signed certificate that contains your public key.
// This is what a certificate authority (like https://letsencrypt.org/)
// would do for you. Notice that it embeds your public key on it.
//
// This is equivalent to generating a certificate with:
// openssl req -new -x509 -key key.pem -out cert.pem -days 365
//
// You can decode the contents of this certificate on your machine by
// running:
// openssl x509 -in cert.pem -text -noout
//
derBytes, _ := x509.CreateCertificate(rand.Reader, &template, &template, &pk.PublicKey, pk)
certOut, _ := os.Create(certFile)
pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
certOut.Close()
log.Printf("Generated file cert.pem with public key:")
// log.Printf("%#v", pk.PublicKey)
log.Printf("%x\r\n\r\n", pk.PublicKey.N)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment