]> Sergey Matveev's repositories - tofuproxy.git/blob - cmd/certgen/main.go
Another refactor
[tofuproxy.git] / cmd / certgen / main.go
1 /*
2 tofuproxy -- HTTP proxy with TLS certificates management
3 Copyright (C) 2021 Sergey Matveev <stargrave@stargrave.org>
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, version 3 of the License.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 package main
19
20 import (
21         "crypto/ecdsa"
22         "crypto/elliptic"
23         "crypto/rand"
24         "crypto/x509"
25         "crypto/x509/pkix"
26         "encoding/pem"
27         "flag"
28         "io"
29         "log"
30         "math/big"
31         "os"
32         "time"
33 )
34
35 func main() {
36         cn := flag.String("cn", "tofuproxy.localhost", "CommonName")
37         crtPath := flag.String("cert", "cert.pem", "Path to server X.509 certificate")
38         prvPath := flag.String("key", "prv.pem", "Path to server PKCS#8 private key")
39         flag.Parse()
40         log.SetFlags(log.Lshortfile)
41
42         prv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
43         if err != nil {
44                 log.Fatalln(err)
45         }
46         pub := prv.Public()
47         notBefore := time.Now()
48         notAfter := notBefore.Add(365 * 24 * time.Hour)
49
50         serialRaw := make([]byte, 16)
51         if _, err = io.ReadFull(rand.Reader, serialRaw); err != nil {
52                 log.Fatalln(err)
53         }
54         serial := big.NewInt(0)
55         serial = serial.SetBytes(serialRaw)
56
57         template := x509.Certificate{
58                 SerialNumber:          serial,
59                 Subject:               pkix.Name{CommonName: *cn},
60                 DNSNames:              []string{*cn},
61                 NotBefore:             notBefore,
62                 NotAfter:              notAfter,
63                 BasicConstraintsValid: true,
64                 IsCA:                  true,
65         }
66         certRaw, err := x509.CreateCertificate(
67                 rand.Reader, &template, &template, pub, prv,
68         )
69         if err != nil {
70                 log.Fatalln(err)
71         }
72         if _, err = x509.ParseCertificate(certRaw); err != nil {
73                 log.Fatalln(err)
74         }
75         pkcs8, err := x509.MarshalPKCS8PrivateKey(prv)
76         if err != nil {
77                 log.Fatalln(err)
78         }
79
80         fd, err := os.OpenFile(*prvPath, os.O_WRONLY|os.O_CREATE, 0600)
81         if err != nil {
82                 log.Fatalln(err)
83         }
84         err = pem.Encode(fd, &pem.Block{Type: "PRIVATE KEY", Bytes: pkcs8})
85         if err != nil {
86                 log.Fatalln(err)
87         }
88         fd.Close()
89
90         fd, err = os.OpenFile(*crtPath, os.O_WRONLY|os.O_CREATE, 0600)
91         err = pem.Encode(fd, &pem.Block{Type: "CERTIFICATE", Bytes: certRaw})
92         if err != nil {
93                 log.Fatalln(err)
94         }
95 }