This repository was archived by the owner on Jul 7, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathkeyGenerator.go
More file actions
115 lines (96 loc) · 2.62 KB
/
Copy pathkeyGenerator.go
File metadata and controls
115 lines (96 loc) · 2.62 KB
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
// SPDX-FileCopyrightText: 2025 Comcast Cable Communications Management, LLC
// SPDX-License-Identifier: Apache-2.0
package main
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/rsa"
"fmt"
"io"
"time"
"github.com/lestrrat-go/jwx/v3/jwa"
"github.com/lestrrat-go/jwx/v3/jwk"
"go.uber.org/fx"
)
// KeyGenerator generates raw keys, e.g. EC and RSA.
//
// A KeyGenerator sets an expires on all keys. The expires value
// for keys is <key rotation> + <token expires> + <1 minute grace>.
// This allows for tokens signed by rotated keys to be validated
// until they expire.
type KeyGenerator struct {
random io.Reader
now func() time.Time
expires time.Duration
idGenerator *IDGenerator
alg jwa.KeyAlgorithm
ec bool
bits int
curve elliptic.Curve
}
func NewKeyGenerator(idGenerator *IDGenerator, cli CLI) (kg *KeyGenerator, err error) {
kg = &KeyGenerator{
random: rand.Reader,
now: time.Now,
expires: cli.KeyRotate + cli.Expires + time.Minute,
idGenerator: idGenerator,
}
switch {
case cli.KeyType == "EC" && cli.KeyCurve == "P-256":
kg.ec = true
kg.curve = elliptic.P256()
kg.alg = jwa.ES256()
case cli.KeyType == "EC" && cli.KeyCurve == "P-384":
kg.ec = true
kg.curve = elliptic.P384()
kg.alg = jwa.ES384()
case cli.KeyType == "EC" && cli.KeyCurve == "P-521":
kg.ec = true
kg.curve = elliptic.P521()
kg.alg = jwa.ES512()
case cli.KeyType == "RSA" && cli.KeySize > 0:
kg.ec = false
kg.bits = cli.KeySize
kg.alg = jwa.RS256()
default:
err = fmt.Errorf("unsupported key parameters: type=%s, size=%d, curve=%s", cli.KeyType, cli.KeySize, cli.KeyCurve)
}
return
}
// generateRaw generates the raw key appropriate for this instance's configuration.
func (kg *KeyGenerator) generateRaw() (raw any, err error) {
// TODO: support other kinds of keys
switch {
case kg.ec:
raw, err = ecdsa.GenerateKey(kg.curve, kg.random)
default:
raw, err = rsa.GenerateKey(kg.random, kg.bits)
}
return
}
// Generate creates a new, random key appropriate for signing and verification.
func (kg *KeyGenerator) Generate() (k Key, err error) {
k = Key{
KID: kg.idGenerator.Generate(16),
Alg: kg.alg,
}
var raw any
raw, err = kg.generateRaw()
if err == nil {
k.Key, err = jwk.Import(raw)
}
if err == nil {
k.Created = kg.now().UTC()
k.Expires = k.Created.Add(kg.expires)
k.Key.Set(jwk.KeyUsageKey, jwk.ForSignature)
k.Key.Set(jwk.KeyOpsKey, jwk.KeyOperationList{jwk.KeyOpSign, jwk.KeyOpVerify})
k.Key.Set(jwk.KeyIDKey, k.KID)
}
return
}
func ProvideKeyGenerator() fx.Option {
return fx.Provide(
NewKeyGenerator,
)
}