-
Notifications
You must be signed in to change notification settings - Fork 0
/
cert.go
130 lines (112 loc) · 2.85 KB
/
cert.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
package main
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"fmt"
"math/big"
"net"
"os"
"strings"
"time"
"github.com/mitchellh/go-homedir"
)
func NewServerCertificate(certfile string, keyfile string) (*tls.Config, error) {
// generate a ec private key
priv, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
// write private key to pem file
privBytes, err := x509.MarshalECPrivateKey(priv)
if nil != err {
return nil, err
}
privPemBlock := &pem.Block{
Type: "EC PRIVATE KEY",
Bytes: privBytes,
}
err = WritePemFile(keyfile, privPemBlock)
if nil != err {
return nil, err
}
// generate self signed certificate
cert := &x509.Certificate{
// Version: 2,
SerialNumber: RandomBigInt(),
Subject: pkix.Name{
CommonName: "localhost",
},
Issuer: pkix.Name{
CommonName: "localhost",
},
IPAddresses: []net.IP{net.IPv4(127, 0, 0, 1), net.IPv6loopback},
NotBefore: time.Now(),
NotAfter: time.Now().AddDate(10, 0, 0),
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
KeyUsage: x509.KeyUsageDigitalSignature,
}
certBytes, err := x509.CreateCertificate(rand.Reader, cert, cert, &priv.PublicKey, priv)
if nil != err {
return nil, err
}
// write create to pem file
certBlock := &pem.Block{
Type: "CERTIFICATE",
Bytes: certBytes,
}
err = WritePemFile(certfile, certBlock)
if nil != err {
return nil, err
}
// create tls config
tlsCfg := &tls.Config{
MinVersion: tls.VersionTLS12,
CurvePreferences: []tls.CurveID{tls.CurveP521, tls.CurveP384, tls.CurveP256},
PreferServerCipherSuites: true,
CipherSuites: []uint16{
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
tls.TLS_RSA_WITH_AES_256_CBC_SHA,
},
}
return tlsCfg, nil
}
func RandomBigInt() *big.Int {
//Max random value, a 130-bits integer, i.e 2^130 - 1
max := new(big.Int)
max.Exp(big.NewInt(2), big.NewInt(130), nil).Sub(max, big.NewInt(1))
//Generate cryptographically strong pseudo-random between 0 - max
n, err := rand.Int(rand.Reader, max)
if err != nil {
return nil
}
return n
}
func ExpandFilePath(path string) string {
exp, _ := homedir.Expand(path)
return exp
}
func WritePemFile(filename string, block *pem.Block) error {
// check if filename end is .pem
if !strings.HasSuffix(filename, ".pem") {
filename = fmt.Sprintf("%s.pem", filename)
}
// expand file path
xfilename := ExpandFilePath(filename)
// open the file
pemfile, err := os.Create(xfilename)
if nil != err {
return fmt.Errorf("Unable to create file %s! Please check file permissions", xfilename)
}
// write pem file
err = pem.Encode(pemfile, block)
if nil != err {
return err
}
// write a success message
pemfile.Close()
return nil
}