/* tofuproxy -- HTTP proxy with TLS certificates management Copyright (C) 2021 Sergey Matveev This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ package main import ( "crypto/ecdsa" "crypto/elliptic" "crypto/rand" "crypto/x509" "crypto/x509/pkix" "encoding/pem" "flag" "io" "log" "math/big" "os" "time" ) func main() { cn := flag.String("cn", "tofuproxy.localhost", "CommonName") crtPath := flag.String("cert", "cert.pem", "Path to server X.509 certificate") prvPath := flag.String("key", "prv.pem", "Path to server PKCS#8 private key") flag.Parse() log.SetFlags(log.Lshortfile) prv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { log.Fatalln(err) } pub := prv.Public() notBefore := time.Now() notAfter := notBefore.Add(365 * 24 * time.Hour) serialRaw := make([]byte, 16) if _, err = io.ReadFull(rand.Reader, serialRaw); err != nil { log.Fatalln(err) } serial := big.NewInt(0) serial = serial.SetBytes(serialRaw) template := x509.Certificate{ SerialNumber: serial, Subject: pkix.Name{CommonName: *cn}, DNSNames: []string{*cn}, NotBefore: notBefore, NotAfter: notAfter, BasicConstraintsValid: true, IsCA: true, } certRaw, err := x509.CreateCertificate( rand.Reader, &template, &template, pub, prv, ) if err != nil { log.Fatalln(err) } if _, err = x509.ParseCertificate(certRaw); err != nil { log.Fatalln(err) } pkcs8, err := x509.MarshalPKCS8PrivateKey(prv) if err != nil { log.Fatalln(err) } fd, err := os.OpenFile(*prvPath, os.O_WRONLY|os.O_CREATE, 0600) if err != nil { log.Fatalln(err) } err = pem.Encode(fd, &pem.Block{Type: "PRIVATE KEY", Bytes: pkcs8}) if err != nil { log.Fatalln(err) } fd.Close() fd, err = os.OpenFile(*crtPath, os.O_WRONLY|os.O_CREATE, 0600) err = pem.Encode(fd, &pem.Block{Type: "CERTIFICATE", Bytes: certRaw}) if err != nil { log.Fatalln(err) } }