Commit 4a2b0f9a authored by Sietse Ringers's avatar Sietse Ringers
Browse files

Merge schememgr, irmatool and irmameta in new executable called irma

parent 64a439e7
......@@ -11,21 +11,18 @@ import (
"github.com/spf13/cobra"
)
// TODO: add flag to update timestamp of irma_configuration folder
var downloadCmd = &cobra.Command{
Use: "download path url...",
Short: "[Experimental] Download a scheme manager",
Long: `The download command downloads and saves a scheme manager given its URL, saving it in path (i.e., an irma_configuration folder).`,
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
return downloadSchemeManager(args[0], args[1:])
Run: func(cmd *cobra.Command, args []string) {
if err := downloadSchemeManager(args[0], args[1:]); err != nil {
die("Downloading scheme failed", err)
}
},
}
func init() {
RootCmd.AddCommand(downloadCmd)
}
func downloadSchemeManager(dest string, urls []string) error {
exists, err := fs.PathExists(dest)
if err != nil {
......@@ -62,8 +59,14 @@ func downloadSchemeManager(dest string, urls []string) error {
managerName := urlparts[len(urlparts)-1]
manager := irma.NewSchemeManager(managerName)
manager.URL = u
conf.InstallSchemeManager(manager)
if err := conf.InstallSchemeManager(manager, nil); err != nil {
return err
}
}
return nil
}
func init() {
schemeCmd.AddCommand(downloadCmd)
}
// Copyright © 2017 Maarten Everts
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// Originally from from github.com/mhe/irmatool/cmd/genkeypair.go.
package cmd
import (
"time"
"errors"
"fmt"
"regexp"
"strconv"
"github.com/mhe/gabi"
"github.com/spf13/cobra"
)
// genkeypairCmd represents the genkeypair command
var genkeypairCmd = &cobra.Command{
Use: "genkeypair",
Short: "Generate an IRMA issuer keypair.",
Long: `The genkeypair command generates an IRMA issuer keypair.`,
RunE: func(cmd *cobra.Command, args []string) error {
keylength, err := cmd.Flags().GetInt("keylength")
if err != nil {
return err
}
counter, err := cmd.Flags().GetUint("counter")
if err != nil {
return err
}
numAttributes, err := cmd.Flags().GetInt("numattributes")
if err != nil {
return err
}
privkeyfile, err := cmd.Flags().GetString("private-key-file")
if err != nil {
return err
}
pubkeyfile, err := cmd.Flags().GetString("public-key-file")
if err != nil {
return err
}
overwrite, err := cmd.Flags().GetBool("force-overwrite")
if err != nil {
return err
}
expiryDateString, err := cmd.Flags().GetString("expirydate")
if err != nil {
return err
}
validFor, err := cmd.Flags().GetString("valid-for")
if err != nil {
return err
}
var expiryDate time.Time
if expiryDateString != "" {
expiryDate, err = time.Parse(time.RFC3339, expiryDateString)
if err != nil {
return err
}
} else {
expiryDate = time.Now()
m := regexp.MustCompile(`^(\d+)([yMdhm])$`).FindStringSubmatch(validFor)
if m == nil {
return errors.New("unable to parse valid-for period")
}
num, err := strconv.Atoi(m[1])
if err != nil {
return errors.New("unable to parse valid-for period")
}
switch m[2] {
case "m":
expiryDate = expiryDate.Add(time.Minute * time.Duration(num))
case "h":
expiryDate = expiryDate.Add(time.Hour * time.Duration(num))
case "d":
expiryDate = expiryDate.AddDate(0, 0, num)
case "M":
expiryDate = expiryDate.AddDate(0, num, 0)
case "y":
expiryDate = expiryDate.AddDate(num, 0, 0)
}
}
// Now generate the key pair
sysParams, ok := gabi.DefaultSystemParameters[keylength]
if !ok {
return fmt.Errorf("Unsupported key length, should be one of %v", gabi.DefaultKeyLengths)
}
privk, pubk, err := gabi.GenerateKeyPair(sysParams, numAttributes, counter, expiryDate)
if err != nil {
return err
}
// TODO: consider support for writing keys to stdout?
if _, err = privk.WriteToFile(privkeyfile, overwrite); err != nil {
return errors.New("private key file already exists, will not overwrite. Check -f flag")
}
if _, err = pubk.WriteToFile(pubkeyfile, overwrite); err != nil {
return errors.New("public key file already exists, will not overwrite. Check -f flag")
}
return nil
},
}
func init() {
RootCmd.AddCommand(genkeypairCmd)
genkeypairCmd.Flags().StringP("private-key-file", "k", "isk.xml", "File to write private key to")
genkeypairCmd.Flags().StringP("public-key-file", "p", "ipk.xml", "File to write public key to")
genkeypairCmd.Flags().StringP("expirydate", "e", "", "Expiry date for the key pair. Specify in RFC3339 (\"2006-01-02T15:04:05+07:00\") format. Alternatively, use the --valid-for option.")
genkeypairCmd.Flags().StringP("valid-for", "v", "1y", "The duration key pair should be valid starting from now. Specify as a number followed by either y, M, d, h, or m (for years, months, days, hours, and minutes, respectively). For example, use \"2y\" for a expiry date 2 years from now. This flag is ignored when expirydate flag is used.")
genkeypairCmd.Flags().IntP("keylength", "l", 1024, "Keylength")
genkeypairCmd.Flags().UintP("counter", "c", 0, "Set the counter (for the number of generated key pairs).")
genkeypairCmd.Flags().IntP("numattributes", "a", 6, "Number of attributes")
genkeypairCmd.Flags().BoolP("force-overwrite", "f", false, "Force overwriting of key files if files already exist. If not set, irmatool will refuse to overwrite existing files.")
}
......@@ -12,8 +12,8 @@ import (
"fmt"
"github.com/privacybydesign/irmago/internal/fs"
"github.com/go-errors/errors"
"github.com/privacybydesign/irmago/internal/fs"
"github.com/spf13/cobra"
)
......@@ -73,7 +73,7 @@ var keygenCmd = &cobra.Command{
}
func init() {
RootCmd.AddCommand(keygenCmd)
schemeCmd.AddCommand(keygenCmd)
keygenCmd.Flags().StringP("privatekey", "s", "sk.pem", "filename for private key")
keygenCmd.Flags().StringP("publickey", "p", "pk.pem", "filename for public key")
}
// irmameta parses and prints info about the specified metadata attribute.
package main
package cmd
import (
"encoding/base64"
"encoding/json"
"fmt"
"os"
"time"
"encoding/json"
"github.com/go-errors/errors"
"github.com/privacybydesign/gabi"
"github.com/privacybydesign/gabi/big"
"github.com/privacybydesign/irmago"
"github.com/privacybydesign/irmago/internal/fs"
"github.com/spf13/cobra"
)
func main() {
if len(os.Args) != 3 {
fmt.Println("Usage: irmago path_to_irma_configuration metadata_attribute_in_decimal")
}
// metaCmd represents the meta command
var metaCmd = &cobra.Command{
Use: "meta irma_configuration attribute",
Short: "Parse an IRMA metadata attribute and print its contents",
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
confpath := args[0]
metaint := new(big.Int)
_, ok := metaint.SetString(args[1], 10)
if !ok {
bts, err := base64.StdEncoding.DecodeString(args[0])
if err != nil {
return errors.WrapPrefix(err, "Could not parse argument as decimal or base64 integer", 0)
}
metaint.SetBytes(bts)
}
metaint := new(big.Int)
_, ok := metaint.SetString(os.Args[2], 10)
if !ok {
bts, err := base64.StdEncoding.DecodeString(os.Args[2])
if err != nil {
fmt.Println("Could not parse argument as decimal or base64 integer: ", err.Error())
os.Exit(1)
if err := printMetadataAttr(metaint, confpath); err != nil {
die("", err)
}
metaint.SetBytes(bts)
}
return nil
},
}
confpath := os.Args[1]
func printMetadataAttr(metaint *big.Int, confpath string) error {
if err := fs.AssertPathExists(confpath); err != nil {
return errors.WrapPrefix(err, "Cannot read irma_configuration", 0)
}
conf, err := irma.NewConfiguration(confpath, "")
if err != nil {
fmt.Println("Failed to parse irma_configuration:", err)
os.Exit(1)
return errors.WrapPrefix(err, "Failed to parse irma_configuration", 0)
}
err = conf.ParseFolder()
if err != nil {
fmt.Println("Failed to parse irma_configuration:", err)
os.Exit(1)
return errors.WrapPrefix(err, "Failed to parse irma_configuration", 0)
}
meta := irma.MetadataFromInt(metaint, conf)
......@@ -68,6 +76,8 @@ func main() {
fmt.Println()
fmt.Println("CredentialType :", prettyprint(typ))
return nil
}
func prettyprint(ob interface{}) string {
......@@ -77,3 +87,7 @@ func prettyprint(ob interface{}) string {
}
return string(b)
}
func init() {
RootCmd.AddCommand(metaCmd)
}
......@@ -9,9 +9,9 @@ import (
// RootCmd represents the base command when called without any subcommands
var RootCmd = &cobra.Command{
Use: "schememgr",
Short: "IRMA scheme manager tool",
Long: `Schememgr is a tool for managing IRMA scheme managers.`,
Use: "irma",
Short: "IRMA toolkit",
Long: `IRMA toolkit`,
}
// Execute adds all child commands to the root command sets flags appropriately.
......@@ -22,3 +22,15 @@ func Execute() {
os.Exit(-1)
}
}
func die(message string, err error) {
var m string
if message != "" {
m = message + ": "
}
if err != nil {
m = m + err.Error()
}
fmt.Println(m)
os.Exit(1)
}
package cmd
import (
"github.com/spf13/cobra"
)
// schemeCmd represents the scheme command
var schemeCmd = &cobra.Command{
Use: "scheme",
Short: "IRMA scheme manager tool",
}
func init() {
RootCmd.AddCommand(schemeCmd)
}
package cmd
import (
"fmt"
"os"
"regexp"
"strconv"
......@@ -35,7 +34,7 @@ var signCmd = &cobra.Command{
}
func init() {
RootCmd.AddCommand(signCmd)
schemeCmd.AddCommand(signCmd)
}
func signManager(args []string) {
......@@ -138,12 +137,3 @@ func calculateFileHash(path string, info os.FileInfo, err error, confpath string
index[relativePath] = hash[:]
return nil
}
func die(message string, err error) {
if err != nil {
fmt.Println(message, err)
} else {
fmt.Println(message)
}
os.Exit(1)
}
......@@ -15,13 +15,15 @@ var updateCmd = &cobra.Command{
Long: `The update command updates a scheme manager within an irma_configuration folder by comparing its index with the online version, and downloading any new and changed files.
Careful: this command could fail and invalidate or destroy your scheme manager folder! Use this only if you can restore it from git or backups.`,
RunE: func(cmd *cobra.Command, args []string) error {
return updateSchemeManager(args)
Run: func(cmd *cobra.Command, args []string) {
if err := updateSchemeManager(args); err != nil {
die("", err)
}
},
}
func init() {
RootCmd.AddCommand(updateCmd)
schemeCmd.AddCommand(updateCmd)
}
func updateSchemeManager(paths []string) error {
......
......@@ -16,13 +16,14 @@ var verifyCmd = &cobra.Command{
Short: "Verify irma_configuration folder correctness and authenticity",
Long: `The verify command parses the specified irma_configuration folder and checks the signatures of the contained scheme managers.`,
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
Run: func(cmd *cobra.Command, args []string) {
err := RunVerify(args[0])
if err == nil {
fmt.Println()
fmt.Println("Verification was successful.")
} else {
die("Verification failed", err)
}
return err
},
}
......@@ -84,5 +85,5 @@ func VerifyIrmaConfiguration(path string) error {
}
func init() {
RootCmd.AddCommand(verifyCmd)
schemeCmd.AddCommand(verifyCmd)
}
package main
import "github.com/privacybydesign/irmago/irma/cmd"
func main() {
cmd.Execute()
}
// schememgr manages signatures on IRMA scheme managers.
// It can generate public-private keypairs for signing their directory structures,
// as well as creating and verifying these signatures.
package main
import "github.com/privacybydesign/irmago/schememgr/cmd"
func main() {
cmd.Execute()
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment