diff --git a/cmd/keygen/main.go b/cmd/keygen/main.go index 8e629da..c330f20 100644 --- a/cmd/keygen/main.go +++ b/cmd/keygen/main.go @@ -11,8 +11,10 @@ var ( createKeyCmd = false getPublicKeyCmd = false createTokenCmd = false + verifyTokenCmd = false debug = false keyFile string + tokenFile string tokenIssuer string tokenPeerID = uuid.New() keySize = 2048 @@ -28,12 +30,17 @@ func init() { &createTokenCmd, "create-token", createTokenCmd, "Create a new signed authentication token", ) + flag.BoolVar( + &verifyTokenCmd, "verify-token", verifyTokenCmd, + "Verify a token generated with the given key", + ) flag.BoolVar( &getPublicKeyCmd, "get-public-key", getPublicKeyCmd, "Get the PEM encoded public key associated with the private key", ) flag.BoolVar(&debug, "debug", debug, "Debug mode") flag.StringVar(&keyFile, "key", keyFile, "Path to the encrypted PEM encoded key") + flag.StringVar(&tokenFile, "token", tokenFile, "Path to the token to verify") flag.StringVar(&tokenIssuer, "token-issuer", tokenIssuer, "Token issuer") flag.StringVar(&tokenPeerID, "token-peer-id", tokenPeerID, "Token peer ID") flag.IntVar(&keySize, "key-size", keySize, "Size of the private key") @@ -48,6 +55,8 @@ func main() { getPublicKey() case createTokenCmd: createToken() + case verifyTokenCmd: + verifyToken() default: flag.Usage() } diff --git a/cmd/keygen/util.go b/cmd/keygen/util.go index af63fdc..ddfe86a 100644 --- a/cmd/keygen/util.go +++ b/cmd/keygen/util.go @@ -2,10 +2,7 @@ package main import ( "bytes" - "crypto/rand" "crypto/rsa" - "crypto/x509" - "encoding/pem" "fmt" "io/ioutil" "os" @@ -47,25 +44,6 @@ func askPassphrase() ([]byte, error) { return passphrase, nil } -func privateKeyToEncryptedPEM(key *rsa.PrivateKey, passphrase []byte) ([]byte, error) { - if passphrase == nil { - return nil, errors.New("passphrase cannot be empty") - } - - // Convert it to pem - block := &pem.Block{ - Type: "RSA PRIVATE KEY", - Bytes: x509.MarshalPKCS1PrivateKey(key), - } - - block, err := x509.EncryptPEMBlock(rand.Reader, block.Type, block.Bytes, passphrase, x509.PEMCipherAES256) - if err != nil { - return nil, errors.WithStack(err) - } - - return pem.EncodeToMemory(block), nil -} - func loadPrivateKey() (*rsa.PrivateKey, error) { if keyFile == "" { return nil, errors.New("you must specify a key file to load") @@ -85,6 +63,19 @@ func loadPrivateKey() (*rsa.PrivateKey, error) { return privateKey, nil } +func loadToken() ([]byte, error) { + if tokenFile == "" { + return nil, errors.New("you must specify a token file to load") + } + + token, err := os.ReadFile(tokenFile) + if err != nil { + return nil, errors.WithStack(err) + } + + return token, nil +} + func handleError(err error) { if !debug { fmt.Printf("%+v\n", errors.WithStack(err)) diff --git a/cmd/keygen/verify_token.go b/cmd/keygen/verify_token.go new file mode 100644 index 0000000..c0d9da7 --- /dev/null +++ b/cmd/keygen/verify_token.go @@ -0,0 +1,55 @@ +package main + +import ( + "encoding/json" + "fmt" + + peering "forge.cadoles.com/Cadoles/go-http-peering" + "github.com/dgrijalva/jwt-go" + "github.com/pkg/errors" +) + +func verifyToken() { + rawToken, err := loadToken() + if err != nil { + handleError(errors.WithStack(err)) + } + + privateKey, err := loadPrivateKey() + if err != nil { + handleError(errors.WithStack(err)) + } + + fn := func(token *jwt.Token) (interface{}, error) { + return &privateKey.PublicKey, nil + } + + token, err := jwt.ParseWithClaims(string(rawToken), &peering.ServerTokenClaims{}, fn) + if err != nil { + validationError, ok := err.(*jwt.ValidationError) + if ok { + handleError(errors.WithStack(validationError.Inner)) + } + + handleError(errors.WithStack(err)) + } + + if !token.Valid { + handleError(errors.New("token is invalid")) + } + + claims, ok := token.Claims.(*peering.ServerTokenClaims) + if !ok { + handleError(errors.New("unexpected token claims")) + } + + data, err := json.MarshalIndent(claims, "", " ") + if err != nil { + handleError(errors.WithStack(err)) + } + + fmt.Println("Token OK.") + fmt.Println("Claims:") + fmt.Println(string(data)) + +}