]> Sergey Matveev's repositories - tofuproxy.git/blobdiff - cmd/certgen/main.go
Another refactor
[tofuproxy.git] / cmd / certgen / main.go
diff --git a/cmd/certgen/main.go b/cmd/certgen/main.go
new file mode 100644 (file)
index 0000000..f4a0d97
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+tofuproxy -- HTTP proxy with TLS certificates management
+Copyright (C) 2021 Sergey Matveev <stargrave@stargrave.org>
+
+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 <http://www.gnu.org/licenses/>.
+*/
+
+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)
+       }
+}