auth: Support for EdDSA JWT algorithm

The golang-jwt library supports this already, so supporting it is just a
matter of wiring things up.

Signed-off-by: Tom Wieczorek <twieczorek@mirantis.com>
This commit is contained in:
Tom Wieczorek 2023-07-05 11:33:08 +02:00
parent 76285f7f0f
commit a8a9ebd281
No known key found for this signature in database
GPG Key ID: FE33A2282371E831
5 changed files with 71 additions and 0 deletions

View File

@ -17,6 +17,7 @@ package auth
import ( import (
"context" "context"
"crypto/ecdsa" "crypto/ecdsa"
"crypto/ed25519"
"crypto/rsa" "crypto/rsa"
"errors" "errors"
"time" "time"
@ -54,6 +55,8 @@ func (t *tokenJWT) info(ctx context.Context, token string, rev uint64) (*AuthInf
return &k.PublicKey, nil return &k.PublicKey, nil
case *ecdsa.PrivateKey: case *ecdsa.PrivateKey:
return &k.PublicKey, nil return &k.PublicKey, nil
case ed25519.PrivateKey:
return k.Public(), nil
default: default:
return t.key, nil return t.key, nil
} }
@ -161,6 +164,10 @@ func newTokenProviderJWT(lg *zap.Logger, optMap map[string]string) (*tokenJWT, e
if _, ok := t.key.(*ecdsa.PublicKey); ok { if _, ok := t.key.(*ecdsa.PublicKey); ok {
t.verifyOnly = true t.verifyOnly = true
} }
case *jwt.SigningMethodEd25519:
if _, ok := t.key.(ed25519.PublicKey); ok {
t.verifyOnly = true
}
case *jwt.SigningMethodRSA, *jwt.SigningMethodRSAPSS: case *jwt.SigningMethodRSA, *jwt.SigningMethodRSAPSS:
if _, ok := t.key.(*rsa.PublicKey); ok { if _, ok := t.key.(*rsa.PublicKey); ok {
t.verifyOnly = true t.verifyOnly = true

View File

@ -31,6 +31,9 @@ const (
jwtECPubKey = "../../tests/fixtures/server-ecdsa.crt" jwtECPubKey = "../../tests/fixtures/server-ecdsa.crt"
jwtECPrivKey = "../../tests/fixtures/server-ecdsa.key.insecure" jwtECPrivKey = "../../tests/fixtures/server-ecdsa.key.insecure"
jwtEdPubKey = "../../tests/fixtures/ed25519-public-key.pem"
jwtEdPrivKey = "../../tests/fixtures/ed25519-private-key.pem"
) )
func TestJWTInfo(t *testing.T) { func TestJWTInfo(t *testing.T) {
@ -63,6 +66,15 @@ func TestJWTInfo(t *testing.T) {
"priv-key": jwtECPrivKey, "priv-key": jwtECPrivKey,
"sign-method": "ES256", "sign-method": "ES256",
}, },
"Ed25519-priv": {
"priv-key": jwtEdPrivKey,
"sign-method": "EdDSA",
},
"Ed25519": {
"pub-key": jwtEdPubKey,
"priv-key": jwtEdPrivKey,
"sign-method": "EdDSA",
},
"HMAC": { "HMAC": {
"priv-key": jwtECPrivKey, // any file, raw bytes used as shared secret "priv-key": jwtECPrivKey, // any file, raw bytes used as shared secret
"sign-method": "HS256", "sign-method": "HS256",

View File

@ -15,7 +15,9 @@
package auth package auth
import ( import (
"crypto"
"crypto/ecdsa" "crypto/ecdsa"
"crypto/ed25519"
"crypto/rsa" "crypto/rsa"
"fmt" "fmt"
"os" "os"
@ -100,6 +102,8 @@ func (opts *jwtOptions) Key() (interface{}, error) {
return opts.rsaKey() return opts.rsaKey()
case *jwt.SigningMethodECDSA: case *jwt.SigningMethodECDSA:
return opts.ecKey() return opts.ecKey()
case *jwt.SigningMethodEd25519:
return opts.edKey()
case *jwt.SigningMethodHMAC: case *jwt.SigningMethodHMAC:
return opts.hmacKey() return opts.hmacKey()
default: default:
@ -189,3 +193,45 @@ func (opts *jwtOptions) ecKey() (interface{}, error) {
return priv, nil return priv, nil
} }
func (opts *jwtOptions) edKey() (interface{}, error) {
var (
priv ed25519.PrivateKey
pub ed25519.PublicKey
err error
)
if len(opts.PrivateKey) > 0 {
var privKey crypto.PrivateKey
privKey, err = jwt.ParseEdPrivateKeyFromPEM(opts.PrivateKey)
if err != nil {
return nil, err
}
priv = privKey.(ed25519.PrivateKey)
}
if len(opts.PublicKey) > 0 {
var pubKey crypto.PublicKey
pubKey, err = jwt.ParseEdPublicKeyFromPEM(opts.PublicKey)
if err != nil {
return nil, err
}
pub = pubKey.(ed25519.PublicKey)
}
if priv == nil {
if pub == nil {
// Neither key given
return nil, ErrMissingKey
}
// Public key only, can verify tokens
return pub, nil
}
// both keys provided, make sure they match
if pub != nil && !pub.Equal(priv.Public()) {
return nil, ErrKeyMismatch
}
return priv, nil
}

View File

@ -0,0 +1,3 @@
-----BEGIN PRIVATE KEY-----
MC4CAQAwBQYDK2VwBCIEIAtiwQ7KeS1I0otY9gw1Ox4av/zQ+wvs/8AIaTkawQ73
-----END PRIVATE KEY-----

3
tests/fixtures/ed25519-public-key.pem vendored Normal file
View File

@ -0,0 +1,3 @@
-----BEGIN PUBLIC KEY-----
MCowBQYDK2VwAyEAuOUxC8Bbn1KqYctlim/MHaP5JrtmeK5xcs+9w506btA=
-----END PUBLIC KEY-----