-
Notifications
You must be signed in to change notification settings - Fork 644
/
gen_staker_key.go
125 lines (111 loc) · 3.71 KB
/
gen_staker_key.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
package staking
import (
"bytes"
"crypto/rand"
"crypto/rsa"
"crypto/tls"
"crypto/x509"
"encoding/pem"
"fmt"
"math/big"
"os"
"path/filepath"
"time"
"github.com/ava-labs/avalanchego/utils/perms"
)
func NewStakerKeys() ([]byte, []byte, error) {
// Create key to sign cert with
key, err := rsa.GenerateKey(rand.Reader, 4096)
if err != nil {
return nil, nil, fmt.Errorf("couldn't generate rsa key: %w", err)
}
// Create self-signed staking cert
certTemplate := &x509.Certificate{
SerialNumber: big.NewInt(0),
NotBefore: time.Date(2000, time.January, 0, 0, 0, 0, 0, time.UTC),
NotAfter: time.Now().AddDate(100, 0, 0),
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageDataEncipherment,
BasicConstraintsValid: true,
}
certBytes, err := x509.CreateCertificate(rand.Reader, certTemplate, certTemplate, &key.PublicKey, key)
if err != nil {
return nil, nil, fmt.Errorf("couldn't create certificate: %w", err)
}
var certBuff bytes.Buffer
if err := pem.Encode(&certBuff, &pem.Block{Type: "CERTIFICATE", Bytes: certBytes}); err != nil {
return nil, nil, fmt.Errorf("couldn't write cert file: %w", err)
}
privBytes, err := x509.MarshalPKCS8PrivateKey(key)
if err != nil {
return nil, nil, fmt.Errorf("couldn't marshal private key: %w", err)
}
var keyBuff bytes.Buffer
if err := pem.Encode(&keyBuff, &pem.Block{Type: "PRIVATE KEY", Bytes: privBytes}); err != nil {
return nil, nil, fmt.Errorf("couldn't write private key: %w", err)
}
return certBuff.Bytes(), keyBuff.Bytes(), nil
}
func NewTLSCert() (*tls.Certificate, error) {
certBytes, keyBytes, err := NewStakerKeys()
if err != nil {
return nil, err
}
cert, err := tls.X509KeyPair(certBytes, keyBytes)
if err != nil {
return nil, err
}
cert.Leaf, err = x509.ParseCertificate(cert.Certificate[0])
if err != nil {
return nil, err
}
return &cert, nil
}
// GenerateStakingKeyCert generates a self-signed TLS key/cert pair to use in staking
// The key and files will be placed at [keyPath] and [certPath], respectively
// If there is already a file at [keyPath], returns nil
func GenerateStakingKeyCert(keyPath, certPath string) error {
// If there is already a file at [keyPath], do nothing
if _, err := os.Stat(keyPath); !os.IsNotExist(err) {
return nil
}
certBytes, keyBytes, err := NewStakerKeys()
if err != nil {
return err
}
// Ensure directory where key/cert will live exist
if err := os.MkdirAll(filepath.Dir(certPath), perms.ReadWriteExecute); err != nil {
return fmt.Errorf("couldn't create path for cert: %w", err)
}
if err := os.MkdirAll(filepath.Dir(keyPath), perms.ReadWriteExecute); err != nil {
return fmt.Errorf("couldn't create path for key: %w", err)
}
// Write cert to disk
certFile, err := os.Create(certPath)
if err != nil {
return fmt.Errorf("couldn't create cert file: %w", err)
}
if _, err := certFile.Write(certBytes); err != nil {
return fmt.Errorf("couldn't write cert file: %w", err)
}
if err := certFile.Close(); err != nil {
return fmt.Errorf("couldn't close cert file: %w", err)
}
if err := os.Chmod(certPath, perms.ReadOnly); err != nil { // Make cert read-only
return fmt.Errorf("couldn't change permissions on cert: %w", err)
}
// Write key to disk
keyOut, err := os.Create(keyPath)
if err != nil {
return fmt.Errorf("couldn't create key file: %w", err)
}
if _, err := keyOut.Write(keyBytes); err != nil {
return fmt.Errorf("couldn't write private key: %w", err)
}
if err := keyOut.Close(); err != nil {
return fmt.Errorf("couldn't close key file: %w", err)
}
if err := os.Chmod(keyPath, perms.ReadOnly); err != nil { // Make key read-only
return fmt.Errorf("couldn't change permissions on key")
}
return nil
}