grim/josetool

Parents ce2261105286
Children b34b5deb7edd
basic signing support. supports headers and claims but fails with ES256 right now, not sure why
  • +2 -0
    main.go
  • +106 -0
    sign.go
  • --- a/main.go Tue Feb 07 06:44:00 2017 +0000
    +++ b/main.go Tue Feb 07 06:48:48 2017 +0000
    @@ -19,6 +19,8 @@
    err = genRSA()
    case ecdsaCmd.FullCommand():
    err = genECDSA()
    + case signCmd.FullCommand():
    + err = sign()
    }
    if err != nil {
    --- /dev/null Thu Jan 01 00:00:00 1970 +0000
    +++ b/sign.go Tue Feb 07 06:48:48 2017 +0000
    @@ -0,0 +1,106 @@
    +package main
    +
    +import (
    + "fmt"
    + "io/ioutil"
    + "strings"
    +
    + "github.com/dgrijalva/jwt-go"
    + "github.com/mendsley/gojwk"
    +)
    +
    +var (
    + signCmd = app.Command("sign", "creates a jwt for the given inputs")
    + signKey = signCmd.Arg("key", "the name of the file that contains the private jwk").Required().File()
    + signHeaders = signCmd.Flag("header", "header to include in the jwt in key=val format").Short('H').Strings()
    + signClaims = signCmd.Flag("claim", "claims to include in the jwt in key=val format").Short('c').Strings()
    +
    + signingMap = map[string]jwt.SigningMethod{
    + "ES256": jwt.SigningMethodES256,
    + "ES384": jwt.SigningMethodES384,
    + "ES512": jwt.SigningMethodES512,
    + "RS256": jwt.SigningMethodRS256,
    + "RS384": jwt.SigningMethodRS384,
    + "RS512": jwt.SigningMethodES512,
    + }
    +)
    +
    +func signGetClaims() (jwt.Claims, error) {
    + claims := jwt.MapClaims{}
    +
    + for _, item := range *signClaims {
    + parts := strings.SplitN(item, "=", 2)
    + if len(parts) != 2 {
    + return nil, fmt.Errorf("invalid argument %v, must use key=val format", item)
    + }
    +
    + claims[parts[0]] = parts[1]
    + }
    +
    + return claims, nil
    +}
    +
    +func signParseHeaders(headers map[string]interface{}) error {
    + for _, item := range *signHeaders {
    + parts := strings.SplitN(item, "=", 2)
    +
    + if len(parts) != 2 {
    + return fmt.Errorf("invalid argument %v, must use key=val format")
    + }
    +
    + headers[parts[0]] = parts[1]
    + }
    +
    + return nil
    +}
    +
    +func sign() error {
    + // read the file
    + data, err := ioutil.ReadAll(*signKey)
    + if err != nil {
    + return err
    + }
    +
    + // unmarshal the jwk
    + key, err := gojwk.Unmarshal(data)
    + if err != nil {
    + return err
    + }
    +
    + // make sure we know how to sign
    + signingMethod, found := signingMap[key.Alg]
    + if !found {
    + return fmt.Errorf("unknown algorithm %s", key.Alg)
    + }
    +
    + // decode the private key from the jwk
    + priv, err := key.DecodePrivateKey()
    + if err != nil {
    + return err
    + }
    +
    + // figure out the claims
    + claims, err := signGetClaims()
    + if err != nil {
    + return err
    + }
    +
    + // generate the token
    + token := jwt.NewWithClaims(signingMethod, claims)
    +
    + // now add the headers
    + err = signParseHeaders(token.Header)
    + if err != nil {
    + return err
    + }
    +
    + // sign the data
    + str, err := token.SignedString(priv)
    + if err != nil {
    + return err
    + }
    +
    + fmt.Printf("%s\n", str)
    +
    + return nil
    +}