This repository was archived by the owner on Mar 28, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 284
/
Copy pathgencerts.go
134 lines (115 loc) · 3.54 KB
/
gencerts.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
package cmd
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"flag"
"math/big"
"net"
"os"
"path"
"strings"
"time"
"github.com/OpenBazaar/openbazaar-go/repo"
)
type GenerateCertificates struct {
DataDir string `short:"d" long:"datadir" description:"specify the data directory to be used"`
Testnet bool `short:"t" long:"testnet" description:"config file is for testnet node"`
Host string `short:"h" long:"host" description:"comma-separated hostnames and IPs to generate a certificate for"`
ValidFor time.Duration `long:"duration" description:"duration that certificate is valid for"`
}
func (x *GenerateCertificates) Execute(args []string) error {
flag.Parse()
// Set repo path
repoPath, err := repo.GetRepoPath(x.Testnet, x.DataDir)
if err != nil {
return err
}
if x.DataDir != "" {
repoPath = x.DataDir
}
// Check if host was entered
if len(x.Host) == 0 {
log.Fatalf("Missing required --host parameter")
}
// Set default duration
if x.ValidFor == 0 {
x.ValidFor = 365 * 24 * time.Hour
}
var priv interface{}
// Generate key
priv, err = rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
log.Fatalf("failed to generate private key: %s", err)
}
// Set creation date
var notBefore = time.Now()
notAfter := notBefore.Add(x.ValidFor)
// Create serial nmuber
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
if err != nil {
log.Fatalf("failed to generate serial number: %s", err)
}
// Check if host ip or dns name and count their quantity
var ipAddresses []net.IP
var dnsNames []string
hosts := strings.Split(x.Host, ",")
for _, h := range hosts {
if ip := net.ParseIP(h); ip != nil {
ipAddresses = append(ipAddresses, ip)
} else {
dnsNames = append(dnsNames, h)
}
}
template := x509.Certificate{
SerialNumber: serialNumber,
IPAddresses: ipAddresses,
DNSNames: dnsNames,
Subject: pkix.Name{
Organization: []string{"OpenBazaar"},
},
NotBefore: notBefore,
NotAfter: notAfter,
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
BasicConstraintsValid: true,
IsCA: true,
}
// Create certificate
derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.(*rsa.PrivateKey).PublicKey, priv)
if err != nil {
log.Fatalf("Failed to create certificate: %s", err)
}
// Create ssl directory
err = os.MkdirAll(path.Join(repoPath, "ssl"), 0755)
if err != nil {
log.Fatalf("Failed to create ssl directory: %s", err)
}
// Create and write cert.pem
certOut, err := os.Create(path.Join(repoPath, "ssl", "cert.pem"))
if err != nil {
log.Fatalf("failed to open cert.pem for writing: %s", err)
}
err = pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
if err != nil {
log.Fatalf("failed to write pem encoding: %s", err)
}
certOut.Close()
log.Noticef("wrote cert.pem\n")
// Create and write key.pem
keyOut, err := os.OpenFile(path.Join(repoPath, "ssl", "key.pem"), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
log.Noticef("failed to open key.pem for writing:", err)
return err
}
err = pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv.(*rsa.PrivateKey))})
if err != nil {
log.Fatalf("failed to write pem encoding: %s", err)
}
keyOut.Close()
log.Noticef("wrote key.pem\n")
return nil
}