From bad7ccf8aa740dcc5ea30350486a1fcbcee71516 Mon Sep 17 00:00:00 2001 From: Alex Vanin Date: Sun, 24 Mar 2024 13:25:34 +0300 Subject: [PATCH] Initial commit --- .gitignore | 1 + README.md | 34 +++++++++++++++++++++ go.mod | 3 ++ server/main.go | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 120 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 go.mod create mode 100644 server/main.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8409297 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +server/*.pem diff --git a/README.md b/README.md new file mode 100644 index 0000000..c171e51 --- /dev/null +++ b/README.md @@ -0,0 +1,34 @@ +# Self Signed Certs + +This app starts HTTPS server with auto-generated self signed certificate. + +Use `-p` to specify server port. Default is `10453`. + +Use `-o` to specify path to output file for the certificate. Default is `./cert.pem` + +## Example + +Start server application + +``` +$ cd server +$ go run main.go -o cert.pem +``` + +Try to connect with default settings and receive error. + +``` +$ curl https://localhost:10453 +curl: (60) SSL certificate problem: self-signed certificate +``` + +Receive 200 OK response after adding `-k` flag. + +``` +$ curl -k https://localhost:10453 +``` + +Receive 200 OK by using `--cacert` option. +``` +$ curl --cacert cert.pem https://localhost:10453 +``` diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..e718b55 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module selfcert + +go 1.22.1 diff --git a/server/main.go b/server/main.go new file mode 100644 index 0000000..cf00fb2 --- /dev/null +++ b/server/main.go @@ -0,0 +1,82 @@ +package main + +import ( + "crypto/rand" + "crypto/rsa" + "crypto/tls" + "crypto/x509" + "crypto/x509/pkix" + "encoding/pem" + "flag" + "fmt" + "log" + "math/big" + "net/http" + "os" + "time" +) + +func main() { + cFile := flag.String("o", "./cert.pem", "Path to write cert file to use in the client") + port := flag.String("p", "10453", "Server port") + flag.Parse() + + cert, key, err := certs(*cFile) + if err != nil { + log.Fatalf("Cannot create certs: %v", err) + } + + kp, err := tls.X509KeyPair(cert, key) + if err != nil { + log.Fatalf("Cannot create key pair: %v", err) + } + + config := &tls.Config{ + Certificates: []tls.Certificate{kp}, + } + + server := &http.Server{ + Addr: ":" + *port, + ReadTimeout: time.Second, + WriteTimeout: time.Second, + TLSConfig: config, + } + + server.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + log.Print("New Message") + w.Header().Set("Hello", "World") + w.WriteHeader(200) + }) + + server.ListenAndServeTLS("", "") +} + +func certs(outCertFile string) (certOut []byte, keyOut []byte, err error) { + privateKey, err := rsa.GenerateKey(rand.Reader, 2048) + if err != nil { + return nil, nil, fmt.Errorf("generate private key: %w", err) + } + + template := x509.Certificate{ + SerialNumber: big.NewInt(1), + Subject: pkix.Name{CommonName: "localhost"}, + NotBefore: time.Now(), + NotAfter: time.Now().Add(time.Hour * 24 * 365), + KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, + BasicConstraintsValid: true, + } + + derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &privateKey.PublicKey, privateKey) + if err != nil { + return nil, nil, fmt.Errorf("create certificate: %w", err) + } + + certOut = pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) + keyOut = pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privateKey)}) + + if len(outCertFile) > 0 { + os.WriteFile(outCertFile, certOut, 0400) + } + + return +}