Skip to content

Commit 82c2134

Browse files
committed
Merge pull request #32 from facchinm/auto_certificate
add generateCert commandline switch
2 parents ebaed24 + e6ba498 commit 82c2134

File tree

5 files changed

+167
-46
lines changed

5 files changed

+167
-46
lines changed

certificates.go

+156
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
// Copyright 2009 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// Generate a self-signed X.509 certificate for a TLS server. Outputs to
6+
// 'cert.pem' and 'key.pem' and will overwrite existing files.
7+
8+
package main
9+
10+
import (
11+
"crypto/ecdsa"
12+
"crypto/elliptic"
13+
"crypto/rand"
14+
"crypto/rsa"
15+
"crypto/x509"
16+
"crypto/x509/pkix"
17+
"encoding/pem"
18+
"fmt"
19+
log "github.com/Sirupsen/logrus"
20+
"io/ioutil"
21+
"math/big"
22+
"net"
23+
"os"
24+
"strings"
25+
"time"
26+
)
27+
28+
var (
29+
host = "localhost"
30+
validFrom = ""
31+
validFor = 365 * 24 * time.Hour * 2 // 2 years
32+
isCA = true
33+
rsaBits = 2048
34+
ecdsaCurve = ""
35+
)
36+
37+
func publicKey(priv interface{}) interface{} {
38+
switch k := priv.(type) {
39+
case *rsa.PrivateKey:
40+
return &k.PublicKey
41+
case *ecdsa.PrivateKey:
42+
return &k.PublicKey
43+
default:
44+
return nil
45+
}
46+
}
47+
48+
func pemBlockForKey(priv interface{}) *pem.Block {
49+
switch k := priv.(type) {
50+
case *rsa.PrivateKey:
51+
return &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(k)}
52+
case *ecdsa.PrivateKey:
53+
b, err := x509.MarshalECPrivateKey(k)
54+
if err != nil {
55+
fmt.Fprintf(os.Stderr, "Unable to marshal ECDSA private key: %v", err)
56+
os.Exit(2)
57+
}
58+
return &pem.Block{Type: "EC PRIVATE KEY", Bytes: b}
59+
default:
60+
return nil
61+
}
62+
}
63+
64+
func generateCertificates() {
65+
66+
var priv interface{}
67+
var err error
68+
switch ecdsaCurve {
69+
case "":
70+
priv, err = rsa.GenerateKey(rand.Reader, rsaBits)
71+
case "P224":
72+
priv, err = ecdsa.GenerateKey(elliptic.P224(), rand.Reader)
73+
case "P256":
74+
priv, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
75+
case "P384":
76+
priv, err = ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
77+
case "P521":
78+
priv, err = ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
79+
default:
80+
fmt.Fprintf(os.Stderr, "Unrecognized elliptic curve: %q", ecdsaCurve)
81+
os.Exit(1)
82+
}
83+
if err != nil {
84+
log.Fatalf("failed to generate private key: %s", err)
85+
}
86+
87+
var notBefore time.Time
88+
if len(validFrom) == 0 {
89+
notBefore = time.Now()
90+
} else {
91+
notBefore, err = time.Parse("Jan 2 15:04:05 2006", validFrom)
92+
if err != nil {
93+
fmt.Fprintf(os.Stderr, "Failed to parse creation date: %s\n", err)
94+
os.Exit(1)
95+
}
96+
}
97+
98+
notAfter := notBefore.Add(validFor)
99+
100+
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
101+
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
102+
if err != nil {
103+
log.Fatalf("failed to generate serial number: %s", err)
104+
}
105+
106+
template := x509.Certificate{
107+
SerialNumber: serialNumber,
108+
Subject: pkix.Name{
109+
Organization: []string{"Arduino LLC US"},
110+
},
111+
NotBefore: notBefore,
112+
NotAfter: notAfter,
113+
114+
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
115+
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
116+
BasicConstraintsValid: true,
117+
}
118+
119+
hosts := strings.Split(host, ",")
120+
for _, h := range hosts {
121+
if ip := net.ParseIP(h); ip != nil {
122+
template.IPAddresses = append(template.IPAddresses, ip)
123+
} else {
124+
template.DNSNames = append(template.DNSNames, h)
125+
}
126+
}
127+
128+
if isCA {
129+
template.IsCA = true
130+
template.KeyUsage |= x509.KeyUsageCertSign
131+
}
132+
133+
derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, publicKey(priv), priv)
134+
if err != nil {
135+
log.Fatalf("Failed to create certificate: %s", err)
136+
}
137+
138+
certOut, err := os.Create("cert.pem")
139+
if err != nil {
140+
log.Fatalf("failed to open cert.pem for writing: %s", err)
141+
}
142+
pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
143+
certOut.Close()
144+
log.Print("written cert.pem\n")
145+
146+
ioutil.WriteFile("cert.cer", derBytes, 0644)
147+
148+
keyOut, err := os.OpenFile("key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
149+
if err != nil {
150+
log.Print("failed to open key.pem for writing:", err)
151+
return
152+
}
153+
pem.Encode(keyOut, pemBlockForKey(priv))
154+
keyOut.Close()
155+
log.Print("written key.pem\n")
156+
}

fakecerts/cert.cer

-776 Bytes
Binary file not shown.

fakecerts/cert.pem

-19
This file was deleted.

fakecerts/key.pem

-27
This file was deleted.

main.go

+11
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ var (
3939
hostname = flag.String("hostname", "unknown-hostname", "Override the hostname we get from the OS")
4040
updateUrl = flag.String("updateUrl", "", "")
4141
appName = flag.String("appName", "", "")
42+
genCert = flag.Bool("generateCert", false, "")
4243
globalToolsMap = make(map[string]string)
4344
tempToolsPath = createToolsDir()
4445
port string
@@ -78,6 +79,11 @@ func main() {
7879

7980
flag.Parse()
8081

82+
if *genCert == true {
83+
generateCertificates()
84+
exit()
85+
}
86+
8187
if *hibernate == false {
8288

8389
go func() {
@@ -233,6 +239,11 @@ func main() {
233239
r.Handle("WSS", "/socket.io/", socketHandler)
234240
r.GET("/info", infoHandler)
235241
go func() {
242+
// check if certificates exist; if not, use plain http
243+
if _, err := os.Stat(filepath.Join(dest, "cert.pem")); os.IsNotExist(err) {
244+
return
245+
}
246+
236247
start := 8990
237248
end := 9000
238249
i := start

0 commit comments

Comments
 (0)