-
Notifications
You must be signed in to change notification settings - Fork 0
/
tls.go
140 lines (120 loc) · 3.75 KB
/
tls.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package main
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"fmt"
"io/ioutil"
"math/big"
"net"
"time"
)
// GenPKITLSConf puts together a strong TLS
// configuration to be used when contacting the
// PKI server. It expects the certificate path
// of the PKI server.
func GenPKITLSConf(certPath string) (*tls.Config, error) {
// Read PKI server TLS certificate from
// specified file system location.
pkiCert, err := ioutil.ReadFile(certPath)
if err != nil {
return nil, err
}
// Create new empty cert pool.
pkiCertRoot := x509.NewCertPool()
// Attempt to add the loaded PKI server certificate.
ok := pkiCertRoot.AppendCertsFromPEM(pkiCert)
if !ok {
return nil, fmt.Errorf("failed appending loaded PKI server TLS certificate to pool")
}
return &tls.Config{
RootCAs: pkiCertRoot,
InsecureSkipVerify: false,
MinVersion: tls.VersionTLS13,
CurvePreferences: []tls.CurveID{tls.X25519},
}, nil
}
// GenPubTLSCertAndConf takes care of generating an
// ephemeral TLS certificate based on Elliptic Curve
// Cryptography for supplied FQDN and IP address to
// listen on. A properly configured TLS configuration
// and the PEM-encoded certificate are returned.
// This function takes heavy inspiration from:
// https://golang.org/src/crypto/tls/generate_cert.go
func GenPubTLSCertAndConf(listenFQDN string, listenIPs []string) (*tls.Config, []byte, error) {
now := time.Now()
// Generate new ephemeral P384 EC secret and public key.
secKey, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
if err != nil {
return nil, nil, err
}
pubKey := &secKey.PublicKey
// Obtain marshaled representation of secret key.
secKeyMarsh, err := x509.MarshalECPrivateKey(secKey)
if err != nil {
return nil, nil, err
}
// Generate a random serial number.
serialNumber, err := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128))
if err != nil {
return nil, nil, err
}
// Prepare certificate template.
certTempl := &x509.Certificate{
SerialNumber: serialNumber,
Subject: pkix.Name{
Organization: []string{"Zeno mix-net"},
},
NotBefore: now,
NotAfter: now.Add(10 * 24 * time.Hour),
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
BasicConstraintsValid: true,
IsCA: true,
}
// Ensure IPs are only added once.
listenIPsMap := make(map[string]bool)
for i := range listenIPs {
listenIPsMap[listenIPs[i]] = true
}
// Parse and add all supplied IP addresses.
for ip := range listenIPsMap {
certTempl.IPAddresses = append(certTempl.IPAddresses, net.ParseIP(ip))
}
// Only specify an FQDN if supplied argument is not empty.
if listenFQDN != "" {
certTempl.DNSNames = []string{listenFQDN}
}
// Generate DER representation of certificate.
certDER, err := x509.CreateCertificate(rand.Reader, certTempl, certTempl, pubKey, secKey)
if err != nil {
return nil, nil, err
}
// Encode certificate to PEM format in memory.
certPEM := pem.EncodeToMemory(&pem.Block{
Type: "CERTIFICATE",
Bytes: certDER,
})
// Encode secret key to PEM format in memory.
secKeyPEM := pem.EncodeToMemory(&pem.Block{
Type: "EC PRIVATE KEY",
Bytes: secKeyMarsh,
})
// Load prepared certificate and secret key into
// TLS certificate representation.
tlsCert, err := tls.X509KeyPair(certPEM, secKeyPEM)
if err != nil {
return nil, nil, err
}
return &tls.Config{
Certificates: []tls.Certificate{tlsCert},
InsecureSkipVerify: false,
MinVersion: tls.VersionTLS13,
CurvePreferences: []tls.CurveID{tls.X25519},
SessionTicketsDisabled: true,
}, certPEM, nil
}