1 package keygen
2
3 import (
4 "crypto"
5 "crypto/ecdsa"
6 "crypto/rand"
7 "encoding/binary"
8 "io"
9
10 "golang.org/x/crypto/curve25519"
11
12 "github.com/lestrrat-go/jwx/internal/ecutil"
13 "github.com/lestrrat-go/jwx/jwa"
14 "github.com/lestrrat-go/jwx/jwe/internal/concatkdf"
15 "github.com/lestrrat-go/jwx/jwk"
16 "github.com/lestrrat-go/jwx/x25519"
17 "github.com/pkg/errors"
18 )
19
20
21 func (k ByteKey) Bytes() []byte {
22 return []byte(k)
23 }
24
25
26 func (g Static) Size() int {
27 return len(g)
28 }
29
30
31 func (g Static) Generate() (ByteSource, error) {
32 buf := make([]byte, g.Size())
33 copy(buf, g)
34 return ByteKey(buf), nil
35 }
36
37
38
39 func NewRandom(n int) Random {
40 return Random{keysize: n}
41 }
42
43
44 func (g Random) Size() int {
45 return g.keysize
46 }
47
48
49 func (g Random) Generate() (ByteSource, error) {
50 buf := make([]byte, g.keysize)
51 if _, err := io.ReadFull(rand.Reader, buf); err != nil {
52 return nil, errors.Wrap(err, "failed to read from rand.Reader")
53 }
54 return ByteKey(buf), nil
55 }
56
57
58 func NewEcdhes(alg jwa.KeyEncryptionAlgorithm, enc jwa.ContentEncryptionAlgorithm, keysize int, pubkey *ecdsa.PublicKey) (*Ecdhes, error) {
59 return &Ecdhes{
60 algorithm: alg,
61 enc: enc,
62 keysize: keysize,
63 pubkey: pubkey,
64 }, nil
65 }
66
67
68 func (g Ecdhes) Size() int {
69 return g.keysize
70 }
71
72
73 func (g Ecdhes) Generate() (ByteSource, error) {
74 priv, err := ecdsa.GenerateKey(g.pubkey.Curve, rand.Reader)
75 if err != nil {
76 return nil, errors.Wrap(err, "failed to generate key for ECDH-ES")
77 }
78
79 var algorithm string
80 if g.algorithm == jwa.ECDH_ES {
81 algorithm = g.enc.String()
82 } else {
83 algorithm = g.algorithm.String()
84 }
85
86 pubinfo := make([]byte, 4)
87 binary.BigEndian.PutUint32(pubinfo, uint32(g.keysize)*8)
88
89 z, _ := priv.PublicKey.Curve.ScalarMult(g.pubkey.X, g.pubkey.Y, priv.D.Bytes())
90 zBytes := ecutil.AllocECPointBuffer(z, priv.PublicKey.Curve)
91 defer ecutil.ReleaseECPointBuffer(zBytes)
92 kdf := concatkdf.New(crypto.SHA256, []byte(algorithm), zBytes, []byte{}, []byte{}, pubinfo, []byte{})
93 kek := make([]byte, g.keysize)
94 if _, err := kdf.Read(kek); err != nil {
95 return nil, errors.Wrap(err, "failed to read kdf")
96 }
97
98 return ByteWithECPublicKey{
99 PublicKey: &priv.PublicKey,
100 ByteKey: ByteKey(kek),
101 }, nil
102 }
103
104
105 func NewX25519(alg jwa.KeyEncryptionAlgorithm, enc jwa.ContentEncryptionAlgorithm, keysize int, pubkey x25519.PublicKey) (*X25519, error) {
106 return &X25519{
107 algorithm: alg,
108 enc: enc,
109 keysize: keysize,
110 pubkey: pubkey,
111 }, nil
112 }
113
114
115 func (g X25519) Size() int {
116 return g.keysize
117 }
118
119
120 func (g X25519) Generate() (ByteSource, error) {
121 pub, priv, err := x25519.GenerateKey(rand.Reader)
122 if err != nil {
123 return nil, errors.Wrap(err, "failed to generate key for X25519")
124 }
125
126 var algorithm string
127 if g.algorithm == jwa.ECDH_ES {
128 algorithm = g.enc.String()
129 } else {
130 algorithm = g.algorithm.String()
131 }
132
133 pubinfo := make([]byte, 4)
134 binary.BigEndian.PutUint32(pubinfo, uint32(g.keysize)*8)
135
136 zBytes, err := curve25519.X25519(priv.Seed(), g.pubkey)
137 if err != nil {
138 return nil, errors.Wrap(err, "failed to compute Z")
139 }
140 kdf := concatkdf.New(crypto.SHA256, []byte(algorithm), zBytes, []byte{}, []byte{}, pubinfo, []byte{})
141 kek := make([]byte, g.keysize)
142 if _, err := kdf.Read(kek); err != nil {
143 return nil, errors.Wrap(err, "failed to read kdf")
144 }
145
146 return ByteWithECPublicKey{
147 PublicKey: pub,
148 ByteKey: ByteKey(kek),
149 }, nil
150 }
151
152
153
154 func (k ByteWithECPublicKey) Populate(h Setter) error {
155 key, err := jwk.New(k.PublicKey)
156 if err != nil {
157 return errors.Wrap(err, "failed to create JWK")
158 }
159
160 if err := h.Set("epk", key); err != nil {
161 return errors.Wrap(err, "failed to write header")
162 }
163 return nil
164 }
165
166
167
168 func (k ByteWithIVAndTag) Populate(h Setter) error {
169 if err := h.Set("iv", k.IV); err != nil {
170 return errors.Wrap(err, "failed to write header")
171 }
172
173 if err := h.Set("tag", k.Tag); err != nil {
174 return errors.Wrap(err, "failed to write header")
175 }
176
177 return nil
178 }
179
180
181
182 func (k ByteWithSaltAndCount) Populate(h Setter) error {
183 if err := h.Set("p2c", k.Count); err != nil {
184 return errors.Wrap(err, "failed to write header")
185 }
186
187 if err := h.Set("p2s", k.Salt); err != nil {
188 return errors.Wrap(err, "failed to write header")
189 }
190
191 return nil
192 }
193
View as plain text