]> Sergey Matveev's repositories - tofuproxy.git/blob - x509.go
Use faster modern EdDSA-based certificates
[tofuproxy.git] / x509.go
1 /*
2 tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU
3              manager, WARC/geminispace browser
4 Copyright (C) 2021-2023 Sergey Matveev <stargrave@stargrave.org>
5
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, version 3 of the License.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 package tofuproxy
20
21 import (
22         "crypto"
23         "crypto/ed25519"
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         pub, prv, err := ed25519.GenerateKey(rand.Reader)
60         if err != nil {
61                 log.Fatalln(err)
62         }
63         notBefore := time.Now()
64         notAfter := notBefore.Add(24 * time.Hour)
65         Serial = Serial.Add(Serial, big.NewInt(1))
66         template := x509.Certificate{
67                 SerialNumber: Serial,
68                 Subject:      pkix.Name{CommonName: host},
69                 DNSNames:     []string{host},
70                 NotBefore:    notBefore,
71                 NotAfter:     notAfter,
72         }
73         certRaw, err := x509.CreateCertificate(
74                 rand.Reader, &template, caCert, pub, caPrv,
75         )
76         if err != nil {
77                 log.Fatalln(err)
78         }
79         cert, err := x509.ParseCertificate(certRaw)
80         if err != nil {
81                 log.Fatalln(err)
82         }
83         return &Keypair{cert, prv}
84 }