@@ -6,6 +6,7 @@ package oauth2
6
6
7
7
import (
8
8
"crypto/ecdsa"
9
+ "crypto/ed25519"
9
10
"crypto/elliptic"
10
11
"crypto/rand"
11
12
"crypto/rsa"
@@ -129,6 +130,57 @@ func (key rsaSingingKey) PreProcessToken(token *jwt.Token) {
129
130
token .Header ["kid" ] = key .id
130
131
}
131
132
133
+ type eddsaSigningKey struct {
134
+ signingMethod jwt.SigningMethod
135
+ key ed25519.PrivateKey
136
+ id string
137
+ }
138
+
139
+ func newEdDSASingingKey (signingMethod jwt.SigningMethod , key ed25519.PrivateKey ) (eddsaSigningKey , error ) {
140
+ kid , err := createPublicKeyFingerprint (key .Public ().(ed25519.PublicKey ))
141
+ if err != nil {
142
+ return eddsaSigningKey {}, err
143
+ }
144
+
145
+ return eddsaSigningKey {
146
+ signingMethod ,
147
+ key ,
148
+ base64 .RawURLEncoding .EncodeToString (kid ),
149
+ }, nil
150
+ }
151
+
152
+ func (key eddsaSigningKey ) IsSymmetric () bool {
153
+ return false
154
+ }
155
+
156
+ func (key eddsaSigningKey ) SigningMethod () jwt.SigningMethod {
157
+ return key .signingMethod
158
+ }
159
+
160
+ func (key eddsaSigningKey ) SignKey () interface {} {
161
+ return key .key
162
+ }
163
+
164
+ func (key eddsaSigningKey ) VerifyKey () interface {} {
165
+ return key .key .Public ()
166
+ }
167
+
168
+ func (key eddsaSigningKey ) ToJWK () (map [string ]string , error ) {
169
+ pubKey := key .key .Public ().(ed25519.PublicKey )
170
+
171
+ return map [string ]string {
172
+ "alg" : key .SigningMethod ().Alg (),
173
+ "kid" : key .id ,
174
+ "kty" : "OKP" ,
175
+ "crv" : "Ed25519" ,
176
+ "x" : base64 .RawURLEncoding .EncodeToString (pubKey ),
177
+ }, nil
178
+ }
179
+
180
+ func (key eddsaSigningKey ) PreProcessToken (token * jwt.Token ) {
181
+ token .Header ["kid" ] = key .id
182
+ }
183
+
132
184
type ecdsaSingingKey struct {
133
185
signingMethod jwt.SigningMethod
134
186
key * ecdsa.PrivateKey
@@ -194,8 +246,8 @@ func createPublicKeyFingerprint(key interface{}) ([]byte, error) {
194
246
return checksum [:], nil
195
247
}
196
248
197
- // CreateJWTSingingKey creates a signing key from an algorithm / key pair.
198
- func CreateJWTSingingKey (algorithm string , key interface {}) (JWTSigningKey , error ) {
249
+ // CreateJWTSigningKey creates a signing key from an algorithm / key pair.
250
+ func CreateJWTSigningKey (algorithm string , key interface {}) (JWTSigningKey , error ) {
199
251
var signingMethod jwt.SigningMethod
200
252
switch algorithm {
201
253
case "HS256" :
@@ -218,11 +270,19 @@ func CreateJWTSingingKey(algorithm string, key interface{}) (JWTSigningKey, erro
218
270
signingMethod = jwt .SigningMethodES384
219
271
case "ES512" :
220
272
signingMethod = jwt .SigningMethodES512
273
+ case "EdDSA" :
274
+ signingMethod = jwt .SigningMethodEdDSA
221
275
default :
222
276
return nil , ErrInvalidAlgorithmType {algorithm }
223
277
}
224
278
225
279
switch signingMethod .(type ) {
280
+ case * jwt.SigningMethodEd25519 :
281
+ privateKey , ok := key .(ed25519.PrivateKey )
282
+ if ! ok {
283
+ return nil , jwt .ErrInvalidKeyType
284
+ }
285
+ return newEdDSASingingKey (signingMethod , privateKey )
226
286
case * jwt.SigningMethodECDSA :
227
287
privateKey , ok := key .(* ecdsa.PrivateKey )
228
288
if ! ok {
@@ -271,17 +331,19 @@ func InitSigningKey() error {
271
331
case "ES384" :
272
332
fallthrough
273
333
case "ES512" :
334
+ fallthrough
335
+ case "EdDSA" :
274
336
key , err = loadOrCreateAsymmetricKey ()
275
337
276
338
default :
277
339
return ErrInvalidAlgorithmType {setting .OAuth2 .JWTSigningAlgorithm }
278
340
}
279
341
280
342
if err != nil {
281
- return fmt .Errorf ("Error while loading or creating symmetric key: %v" , err )
343
+ return fmt .Errorf ("Error while loading or creating JWT key: %v" , err )
282
344
}
283
345
284
- signingKey , err := CreateJWTSingingKey (setting .OAuth2 .JWTSigningAlgorithm , key )
346
+ signingKey , err := CreateJWTSigningKey (setting .OAuth2 .JWTSigningAlgorithm , key )
285
347
if err != nil {
286
348
return err
287
349
}
@@ -324,10 +386,15 @@ func loadOrCreateAsymmetricKey() (interface{}, error) {
324
386
if ! isExist {
325
387
err := func () error {
326
388
key , err := func () (interface {}, error ) {
327
- if strings .HasPrefix (setting .OAuth2 .JWTSigningAlgorithm , "RS" ) {
389
+ switch {
390
+ case strings .HasPrefix (setting .OAuth2 .JWTSigningAlgorithm , "RS" ):
328
391
return rsa .GenerateKey (rand .Reader , 4096 )
392
+ case setting .OAuth2 .JWTSigningAlgorithm == "EdDSA" :
393
+ _ , pk , err := ed25519 .GenerateKey (rand .Reader )
394
+ return pk , err
395
+ default :
396
+ return ecdsa .GenerateKey (elliptic .P256 (), rand .Reader )
329
397
}
330
- return ecdsa .GenerateKey (elliptic .P256 (), rand .Reader )
331
398
}()
332
399
if err != nil {
333
400
return err
0 commit comments