forked from lestrrat-go/jwx
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Start giving some love that it deserves to the jwx command
- Loading branch information
Showing
6 changed files
with
354 additions
and
148 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
module github.com/lestrrat-go/jwx/cmd/jwx | ||
|
||
go 1.16 | ||
|
||
require ( | ||
github.com/lestrrat-go/jwx v1.1.0 | ||
github.com/pkg/errors v0.9.1 | ||
github.com/urfave/cli/v2 v2.3.0 | ||
) | ||
|
||
replace github.com/lestrrat-go/jwx => ../.. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= | ||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= | ||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= | ||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= | ||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
github.com/goccy/go-json v0.3.5 h1:HqrLjEWx7hD62JRhBh+mHv+rEEzBANIu6O0kbDlaLzU= | ||
github.com/goccy/go-json v0.3.5/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= | ||
github.com/lestrrat-go/backoff/v2 v2.0.7 h1:i2SeK33aOFJlUNJZzf2IpXRBvqBBnaGXfY5Xaop/GsE= | ||
github.com/lestrrat-go/backoff/v2 v2.0.7/go.mod h1:rHP/q/r9aT27n24JQLa7JhSQZCKBBOiM/uP402WwN8Y= | ||
github.com/lestrrat-go/codegen v1.0.0/go.mod h1:JhJw6OQAuPEfVKUCLItpaVLumDGWQznd1VaXrBk9TdM= | ||
github.com/lestrrat-go/httpcc v1.0.0 h1:FszVC6cKfDvBKcJv646+lkh4GydQg2Z29scgUfkOpYc= | ||
github.com/lestrrat-go/httpcc v1.0.0/go.mod h1:tGS/u00Vh5N6FHNkExqGGNId8e0Big+++0Gf8MBnAvE= | ||
github.com/lestrrat-go/iter v1.0.0 h1:QD+hHQPDSHC4rCJkZYY/yXChYr/vjfBopKekTc+7l4Q= | ||
github.com/lestrrat-go/iter v1.0.0/go.mod h1:zIdgO1mRKhn8l9vrZJZz9TUMMFbQbLeTsbqPDrJ/OJc= | ||
github.com/lestrrat-go/option v0.0.0-20210103042652-6f1ecfceda35/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I= | ||
github.com/lestrrat-go/option v1.0.0 h1:WqAWL8kh8VcSoD6xjSH34/1m8yxluXQbDeKNfvFeEO4= | ||
github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I= | ||
github.com/lestrrat-go/pdebug/v3 v3.0.1 h1:3G5sX/aw/TbMTtVc9U7IHBWRZtMvwvBziF1e4HoQtv8= | ||
github.com/lestrrat-go/pdebug/v3 v3.0.1/go.mod h1:za+m+Ve24yCxTEhR59N7UlnJomWwCiIqbJRmKeiADU4= | ||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= | ||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= | ||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= | ||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= | ||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= | ||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= | ||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= | ||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= | ||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||
github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= | ||
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= | ||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | ||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | ||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | ||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= | ||
golang.org/x/crypto v0.0.0-20201217014255-9d1352758620 h1:3wPMTskHO3+O6jqTEXyFcsnuxMQOqYSaHsDxcbUXpqA= | ||
golang.org/x/crypto v0.0.0-20201217014255-9d1352758620/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= | ||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | ||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | ||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | ||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | ||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= | ||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= | ||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= | ||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= | ||
golang.org/x/tools v0.0.0-20200918232735-d647fc253266/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= | ||
golang.org/x/tools v0.0.0-20210114065538-d78b04bdf963/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= | ||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= | ||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
package main | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"io" | ||
"io/ioutil" | ||
"os" | ||
|
||
"github.com/lestrrat-go/jwx/jwk" | ||
"github.com/pkg/errors" | ||
"github.com/urfave/cli/v2" | ||
) | ||
|
||
func getSource(c *cli.Context) (io.ReadCloser, error) { | ||
var src io.ReadCloser | ||
if c.Bool("stdin") { | ||
src = io.NopCloser(os.Stdin) | ||
} else { | ||
file := c.Args().Get(0) | ||
if file == "" { | ||
return nil, errors.New(`filename required withot -stdin`) | ||
} | ||
f, err := os.Open(file) | ||
if err != nil { | ||
return nil, errors.Wrapf(err, `failed to open file %s`, file) | ||
} | ||
src = f | ||
} | ||
return src, nil | ||
} | ||
|
||
func makeJwkCmd() *cli.Command { | ||
var cmd cli.Command | ||
cmd.Name = "jwk" | ||
cmd.Usage = "Work with JWK and JWK sets" | ||
|
||
// jwk pem ... | ||
cmd.Subcommands = []*cli.Command{ | ||
makeJwkParseCmd(), | ||
makeJwkFormatCmd(), | ||
} | ||
return &cmd | ||
} | ||
|
||
func makeJwkFormatCmd() *cli.Command { | ||
var cmd cli.Command | ||
cmd.Name = "format" | ||
cmd.Usage = "Format JWK" | ||
cmd.Flags = []cli.Flag{ | ||
&cli.StringFlag{Name: "format", Value: "json"}, | ||
&cli.BoolFlag{Name: "stdin", Value: false}, | ||
} | ||
|
||
// jwx jwk format <file> | ||
cmd.Action = func(c *cli.Context) error { | ||
src, err := getSource(c) | ||
if err != nil { | ||
return err | ||
} | ||
defer src.Close() | ||
|
||
buf, err := ioutil.ReadAll(src) | ||
if err != nil { | ||
return errors.Wrap(err, `failed to read data from source`) | ||
} | ||
|
||
key, err := jwk.ParseKey(buf) | ||
if err != nil { | ||
return errors.Wrap(err, `failed to parse key`) | ||
} | ||
|
||
switch format := c.String("format"); format { | ||
case "json": | ||
buf, err = json.MarshalIndent(key, "", " ") | ||
if err != nil { | ||
return errors.Wrap(err, `failed to format key in JSON format`) | ||
} | ||
case "pem": | ||
buf, err = jwk.Pem(key) | ||
if err != nil { | ||
return errors.Wrap(err, `failed to format key in PEM format`) | ||
} | ||
} | ||
|
||
fmt.Printf("%s\n", buf) | ||
return nil | ||
} | ||
return &cmd | ||
} | ||
|
||
func makeJwkParseCmd() *cli.Command { | ||
var cmd cli.Command | ||
cmd.Name = "parse" | ||
cmd.Usage = "Parse JWK" | ||
cmd.Flags = []cli.Flag{ | ||
&cli.StringFlag{Name: "format", Value: "json"}, | ||
&cli.BoolFlag{Name: "stdin", Value: false}, | ||
} | ||
|
||
// jwx jwk parse <file> | ||
cmd.Action = func(c *cli.Context) error { | ||
src, err := getSource(c) | ||
if err != nil { | ||
return err | ||
} | ||
defer src.Close() | ||
|
||
buf, err := ioutil.ReadAll(src) | ||
if err != nil { | ||
return errors.Wrap(err, `failed to read data from source`) | ||
} | ||
|
||
var options []jwk.ParseKeyOption | ||
switch format := c.String("format"); format { | ||
case "json": | ||
case "pem": | ||
options = append(options, jwk.WithPEM(true)) | ||
default: | ||
return errors.Errorf(`invalid format %s`, format) | ||
} | ||
|
||
key, err := jwk.ParseKey(buf, options...) | ||
if err != nil { | ||
return errors.Wrap(err, `failed to parse key`) | ||
} | ||
|
||
buf, err = json.Marshal(key) | ||
if err != nil { | ||
return errors.Wrap(err, `failed to marshal key into JSON format`) | ||
} | ||
fmt.Fprintf(os.Stdout, "%s\n", buf) | ||
return nil | ||
} | ||
return &cmd | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,159 +1,18 @@ | ||
package main | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"encoding/json" | ||
"flag" | ||
"fmt" | ||
"io" | ||
"log" | ||
"os" | ||
|
||
"github.com/lestrrat-go/jwx/jwk" | ||
"github.com/lestrrat-go/jwx/jws" | ||
"github.com/pkg/errors" | ||
"github.com/urfave/cli/v2" | ||
) | ||
|
||
func main() { | ||
os.Exit(_main()) | ||
} | ||
|
||
type JWKConfig struct { | ||
JWKLocation string | ||
Payload string | ||
} | ||
|
||
type JWEConfig struct { | ||
Algorithm string | ||
} | ||
|
||
func _main() int { | ||
var f func() int | ||
|
||
if len(os.Args) < 2 { | ||
f = doHelp | ||
} else { | ||
switch os.Args[1] { | ||
case "jwk": | ||
f = doJWK | ||
case "jwe": | ||
f = doJWE | ||
default: | ||
f = doHelp | ||
} | ||
|
||
os.Args = os.Args[1:] | ||
} | ||
return f() | ||
} | ||
|
||
func doHelp() int { | ||
fmt.Println(`jwx [command] [args]`) | ||
return 0 | ||
} | ||
|
||
func doJWE() int { | ||
c := JWEConfig{} | ||
flag.StringVar(&c.Algorithm, "alg", "", "Key encryption algorithm") | ||
flag.Parse() | ||
|
||
return 0 | ||
} | ||
|
||
func doJWK() int { | ||
c := JWKConfig{} | ||
flag.StringVar(&c.JWKLocation, "jwk", "", "JWK location, either a local file or a URL") | ||
flag.Parse() | ||
|
||
if c.JWKLocation == "" { | ||
fmt.Printf("-jwk must be specified\n") | ||
return 1 | ||
} | ||
var app cli.App | ||
app.Commands = append(app.Commands, makeJwkCmd()) | ||
|
||
key, err := jwk.Fetch(context.TODO(), c.JWKLocation) | ||
if err != nil { | ||
log.Printf("%s", err) | ||
return 0 | ||
if err := app.Run(os.Args); err != nil { | ||
fmt.Fprintf(os.Stderr, "%s\n", err) | ||
os.Exit(1) | ||
} | ||
|
||
keybuf, err := json.MarshalIndent(key, "", " ") | ||
if err != nil { | ||
log.Printf("%s", err) | ||
return 0 | ||
} | ||
log.Printf("=== JWK ===") | ||
for _, l := range bytes.Split(keybuf, []byte{'\n'}) { | ||
log.Printf("%s", l) | ||
} | ||
|
||
// TODO make it flexible | ||
firstKey, ok := key.Get(0) | ||
if !ok { | ||
log.Printf("empty keyset") | ||
return 0 | ||
} | ||
|
||
var pubkey interface{} | ||
if err := firstKey.Raw(&pubkey); err != nil { | ||
log.Printf("%s", err) | ||
return 0 | ||
} | ||
|
||
var src io.Reader | ||
if c.Payload == "" { | ||
src = os.Stdin | ||
} else { | ||
f, err := os.Open(c.Payload) | ||
if err != nil { | ||
log.Printf("%s", errors.Wrap(err, "failed to open file "+c.Payload)) | ||
return 1 | ||
} | ||
src = f | ||
defer f.Close() | ||
} | ||
|
||
var buf bytes.Buffer | ||
src = io.TeeReader(src, &buf) | ||
|
||
message, err := jws.ParseReader(src) | ||
if err != nil { | ||
log.Printf("%s", err) | ||
return 0 | ||
} | ||
|
||
log.Printf("=== Payload ===") | ||
// See if this is JSON. if it is, display it nicely | ||
m := map[string]interface{}{} | ||
if err := json.Unmarshal(message.Payload(), &m); err == nil { | ||
payloadbuf, err := json.MarshalIndent(m, "", " ") | ||
if err != nil { | ||
log.Printf("%s", errors.Wrap(err, "failed to marshal payload")) | ||
return 0 | ||
} | ||
for _, l := range bytes.Split(payloadbuf, []byte{'\n'}) { | ||
log.Printf("%s", l) | ||
} | ||
} else { | ||
log.Printf("%s", message.Payload()) | ||
} | ||
|
||
for i, sig := range message.Signatures() { | ||
log.Printf("=== Signature %d ===", i) | ||
sigbuf, err := json.MarshalIndent(sig, "", " ") | ||
if err != nil { | ||
log.Printf("%s", errors.Wrap(err, "failed to marshal signature as JSON")) | ||
return 0 | ||
} | ||
for _, l := range bytes.Split(sigbuf, []byte{'\n'}) { | ||
log.Printf("%s", l) | ||
} | ||
|
||
alg := sig.ProtectedHeaders().Algorithm() | ||
if _, err := jws.Verify(buf.Bytes(), alg, pubkey); err == nil { | ||
log.Printf("=== Verified with signature %d! ===", i) | ||
} | ||
} | ||
|
||
return 1 | ||
} |
Oops, something went wrong.