]> Sergey Matveev's repositories - tofuproxy.git/blob - x509.go
Refactoring
[tofuproxy.git] / x509.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 tofuproxy
19
20 import (
21         "crypto"
22         "crypto/ecdsa"
23         "crypto/elliptic"
24         "crypto/rand"
25         "crypto/x509"
26         "crypto/x509/pkix"
27         "log"
28         "math/big"
29         "sync"
30         "time"
31 )
32
33 type Keypair struct {
34         cert *x509.Certificate
35         prv  crypto.PrivateKey
36 }
37
38 var (
39         hostCerts  = make(map[string]*Keypair)
40         hostCertsM sync.Mutex
41         Serial     *big.Int
42 )
43
44 func init() {
45         max := big.NewInt(0)
46         max = max.SetBit(max, 128, 1)
47         var err error
48         Serial, err = rand.Int(rand.Reader, max)
49         if err != nil {
50                 panic(err)
51         }
52 }
53
54 func newKeypair(
55         host string,
56         caCert *x509.Certificate,
57         caPrv crypto.PrivateKey,
58 ) *Keypair {
59         prv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
60         if err != nil {
61                 log.Fatalln(err)
62         }
63         pub := prv.Public()
64         notBefore := time.Now()
65         notAfter := notBefore.Add(24 * time.Hour)
66         Serial = Serial.Add(Serial, big.NewInt(1))
67         template := x509.Certificate{
68                 SerialNumber: Serial,
69                 Subject:      pkix.Name{CommonName: host},
70                 DNSNames:     []string{host},
71                 NotBefore:    notBefore,
72                 NotAfter:     notAfter,
73         }
74         certRaw, err := x509.CreateCertificate(
75                 rand.Reader, &template, caCert, pub, caPrv,
76         )
77         if err != nil {
78                 log.Fatalln(err)
79         }
80         cert, err := x509.ParseCertificate(certRaw)
81         if err != nil {
82                 log.Fatalln(err)
83         }
84         return &Keypair{cert, prv}
85 }