1
16
17
18 package keyutil
19
20 import (
21 "crypto"
22 "crypto/ecdsa"
23 "crypto/elliptic"
24 cryptorand "crypto/rand"
25 "crypto/rsa"
26 "crypto/x509"
27 "encoding/pem"
28 "fmt"
29 "os"
30 "path/filepath"
31 )
32
33 const (
34
35 ECPrivateKeyBlockType = "EC PRIVATE KEY"
36
37 RSAPrivateKeyBlockType = "RSA PRIVATE KEY"
38
39 PrivateKeyBlockType = "PRIVATE KEY"
40
41 PublicKeyBlockType = "PUBLIC KEY"
42 )
43
44
45 func MakeEllipticPrivateKeyPEM() ([]byte, error) {
46 privateKey, err := ecdsa.GenerateKey(elliptic.P256(), cryptorand.Reader)
47 if err != nil {
48 return nil, err
49 }
50
51 derBytes, err := x509.MarshalECPrivateKey(privateKey)
52 if err != nil {
53 return nil, err
54 }
55
56 privateKeyPemBlock := &pem.Block{
57 Type: ECPrivateKeyBlockType,
58 Bytes: derBytes,
59 }
60 return pem.EncodeToMemory(privateKeyPemBlock), nil
61 }
62
63
64
65
66
67 func WriteKey(keyPath string, data []byte) error {
68 if err := os.MkdirAll(filepath.Dir(keyPath), os.FileMode(0755)); err != nil {
69 return err
70 }
71 return os.WriteFile(keyPath, data, os.FileMode(0600))
72 }
73
74
75
76 func LoadOrGenerateKeyFile(keyPath string) (data []byte, wasGenerated bool, err error) {
77 loadedData, err := os.ReadFile(keyPath)
78
79 if err == nil && verifyKeyData(loadedData) {
80 return loadedData, false, err
81 }
82 if !os.IsNotExist(err) {
83 return nil, false, fmt.Errorf("error loading key from %s: %v", keyPath, err)
84 }
85
86 generatedData, err := MakeEllipticPrivateKeyPEM()
87 if err != nil {
88 return nil, false, fmt.Errorf("error generating key: %v", err)
89 }
90 if err := WriteKey(keyPath, generatedData); err != nil {
91 return nil, false, fmt.Errorf("error writing key to %s: %v", keyPath, err)
92 }
93 return generatedData, true, nil
94 }
95
96
97
98 func MarshalPrivateKeyToPEM(privateKey crypto.PrivateKey) ([]byte, error) {
99 switch t := privateKey.(type) {
100 case *ecdsa.PrivateKey:
101 derBytes, err := x509.MarshalECPrivateKey(t)
102 if err != nil {
103 return nil, err
104 }
105 block := &pem.Block{
106 Type: ECPrivateKeyBlockType,
107 Bytes: derBytes,
108 }
109 return pem.EncodeToMemory(block), nil
110 case *rsa.PrivateKey:
111 block := &pem.Block{
112 Type: RSAPrivateKeyBlockType,
113 Bytes: x509.MarshalPKCS1PrivateKey(t),
114 }
115 return pem.EncodeToMemory(block), nil
116 default:
117 return nil, fmt.Errorf("private key is not a recognized type: %T", privateKey)
118 }
119 }
120
121
122
123 func PrivateKeyFromFile(file string) (interface{}, error) {
124 data, err := os.ReadFile(file)
125 if err != nil {
126 return nil, err
127 }
128 key, err := ParsePrivateKeyPEM(data)
129 if err != nil {
130 return nil, fmt.Errorf("error reading private key file %s: %v", file, err)
131 }
132 return key, nil
133 }
134
135
136
137 func PublicKeysFromFile(file string) ([]interface{}, error) {
138 data, err := os.ReadFile(file)
139 if err != nil {
140 return nil, err
141 }
142 keys, err := ParsePublicKeysPEM(data)
143 if err != nil {
144 return nil, fmt.Errorf("error reading public key file %s: %v", file, err)
145 }
146 return keys, nil
147 }
148
149
150 func verifyKeyData(data []byte) bool {
151 if len(data) == 0 {
152 return false
153 }
154 _, err := ParsePrivateKeyPEM(data)
155 return err == nil
156 }
157
158
159
160 func ParsePrivateKeyPEM(keyData []byte) (interface{}, error) {
161 var privateKeyPemBlock *pem.Block
162 for {
163 privateKeyPemBlock, keyData = pem.Decode(keyData)
164 if privateKeyPemBlock == nil {
165 break
166 }
167
168 switch privateKeyPemBlock.Type {
169 case ECPrivateKeyBlockType:
170
171 if key, err := x509.ParseECPrivateKey(privateKeyPemBlock.Bytes); err == nil {
172 return key, nil
173 }
174 case RSAPrivateKeyBlockType:
175
176 if key, err := x509.ParsePKCS1PrivateKey(privateKeyPemBlock.Bytes); err == nil {
177 return key, nil
178 }
179 case PrivateKeyBlockType:
180
181 if key, err := x509.ParsePKCS8PrivateKey(privateKeyPemBlock.Bytes); err == nil {
182 return key, nil
183 }
184 }
185
186
187
188 }
189
190
191 return nil, fmt.Errorf("data does not contain a valid RSA or ECDSA private key")
192 }
193
194
195
196 func ParsePublicKeysPEM(keyData []byte) ([]interface{}, error) {
197 var block *pem.Block
198 keys := []interface{}{}
199 for {
200
201 block, keyData = pem.Decode(keyData)
202 if block == nil {
203 break
204 }
205
206
207 if privateKey, err := parseRSAPrivateKey(block.Bytes); err == nil {
208 keys = append(keys, &privateKey.PublicKey)
209 continue
210 }
211 if publicKey, err := parseRSAPublicKey(block.Bytes); err == nil {
212 keys = append(keys, publicKey)
213 continue
214 }
215 if privateKey, err := parseECPrivateKey(block.Bytes); err == nil {
216 keys = append(keys, &privateKey.PublicKey)
217 continue
218 }
219 if publicKey, err := parseECPublicKey(block.Bytes); err == nil {
220 keys = append(keys, publicKey)
221 continue
222 }
223
224
225
226 }
227
228 if len(keys) == 0 {
229 return nil, fmt.Errorf("data does not contain any valid RSA or ECDSA public keys")
230 }
231 return keys, nil
232 }
233
234
235 func parseRSAPublicKey(data []byte) (*rsa.PublicKey, error) {
236 var err error
237
238
239 var parsedKey interface{}
240 if parsedKey, err = x509.ParsePKIXPublicKey(data); err != nil {
241 if cert, err := x509.ParseCertificate(data); err == nil {
242 parsedKey = cert.PublicKey
243 } else {
244 return nil, err
245 }
246 }
247
248
249 var pubKey *rsa.PublicKey
250 var ok bool
251 if pubKey, ok = parsedKey.(*rsa.PublicKey); !ok {
252 return nil, fmt.Errorf("data doesn't contain valid RSA Public Key")
253 }
254
255 return pubKey, nil
256 }
257
258
259 func parseRSAPrivateKey(data []byte) (*rsa.PrivateKey, error) {
260 var err error
261
262
263 var parsedKey interface{}
264 if parsedKey, err = x509.ParsePKCS1PrivateKey(data); err != nil {
265 if parsedKey, err = x509.ParsePKCS8PrivateKey(data); err != nil {
266 return nil, err
267 }
268 }
269
270
271 var privKey *rsa.PrivateKey
272 var ok bool
273 if privKey, ok = parsedKey.(*rsa.PrivateKey); !ok {
274 return nil, fmt.Errorf("data doesn't contain valid RSA Private Key")
275 }
276
277 return privKey, nil
278 }
279
280
281 func parseECPublicKey(data []byte) (*ecdsa.PublicKey, error) {
282 var err error
283
284
285 var parsedKey interface{}
286 if parsedKey, err = x509.ParsePKIXPublicKey(data); err != nil {
287 if cert, err := x509.ParseCertificate(data); err == nil {
288 parsedKey = cert.PublicKey
289 } else {
290 return nil, err
291 }
292 }
293
294
295 var pubKey *ecdsa.PublicKey
296 var ok bool
297 if pubKey, ok = parsedKey.(*ecdsa.PublicKey); !ok {
298 return nil, fmt.Errorf("data doesn't contain valid ECDSA Public Key")
299 }
300
301 return pubKey, nil
302 }
303
304
305 func parseECPrivateKey(data []byte) (*ecdsa.PrivateKey, error) {
306 var err error
307
308
309 var parsedKey interface{}
310 if parsedKey, err = x509.ParseECPrivateKey(data); err != nil {
311 return nil, err
312 }
313
314
315 var privKey *ecdsa.PrivateKey
316 var ok bool
317 if privKey, ok = parsedKey.(*ecdsa.PrivateKey); !ok {
318 return nil, fmt.Errorf("data doesn't contain valid ECDSA Private Key")
319 }
320
321 return privKey, nil
322 }
323
View as plain text