-
-
Notifications
You must be signed in to change notification settings - Fork 548
/
certificates.go
98 lines (79 loc) · 2.47 KB
/
certificates.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
package gateway
import (
"bytes"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"io/ioutil"
"log"
"math/big"
"time"
"github.com/pkg/errors"
"github.com/brocaar/lorawan"
)
// GenerateClientCertificate returns a client-certificate for the given gateway ID.
func GenerateClientCertificate(gatewayID lorawan.EUI64) (time.Time, []byte, []byte, []byte, error) {
if caCert == "" || caKey == "" {
return time.Time{}, nil, nil, nil, errors.New("no ca certificate or ca key configured")
}
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: %v", err)
}
caCertB, err := ioutil.ReadFile(caCert)
if err != nil {
return time.Time{}, nil, nil, nil, errors.Wrap(err, "read ca cert file error")
}
caKeyPair, err := tls.LoadX509KeyPair(caCert, caKey)
if err != nil {
return time.Time{}, nil, nil, nil, errors.Wrap(err, "load ca key-pair error")
}
caCert, err := x509.ParseCertificate(caKeyPair.Certificate[0])
if err != nil {
return time.Time{}, nil, nil, nil, errors.Wrap(err, "parse certificate error")
}
expiresAt := time.Now().Add(tlsLifetime)
cert := &x509.Certificate{
SerialNumber: serialNumber,
Subject: pkix.Name{
CommonName: gatewayID.String(),
},
NotBefore: time.Now(),
NotAfter: expiresAt,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
KeyUsage: x509.KeyUsageDigitalSignature,
}
certPrivKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
return time.Time{}, nil, nil, nil, errors.Wrap(err, "generate key error")
}
certBytes, err := x509.CreateCertificate(rand.Reader, cert, caCert, &certPrivKey.PublicKey, caKeyPair.PrivateKey)
if err != nil {
return time.Time{}, nil, nil, nil, errors.Wrap(err, "create certificate error")
}
caPEM := new(bytes.Buffer)
pem.Encode(caPEM, &pem.Block{
Type: "CERTIFICATE",
Bytes: caKeyPair.Certificate[0],
})
certPEM := new(bytes.Buffer)
pem.Encode(certPEM, &pem.Block{
Type: "CERTIFICATE",
Bytes: certBytes,
})
b, err := x509.MarshalECPrivateKey(certPrivKey)
if err != nil {
return time.Time{}, nil, nil, nil, errors.Wrap(err, "create certificate error")
}
certPrivKeyPEM := new(bytes.Buffer)
pem.Encode(certPrivKeyPEM, &pem.Block{
Type: "EC PRIVATE KEY",
Bytes: b,
})
return expiresAt, caCertB, certPEM.Bytes(), certPrivKeyPEM.Bytes(), nil
}