diff options
Diffstat (limited to 'cmd')
| -rw-r--r-- | cmd/sigsum-debug/head/consistency/consistency.go | 9 | ||||
| -rw-r--r-- | cmd/sigsum-debug/head/head.go | 103 | ||||
| -rw-r--r-- | cmd/sigsum-debug/head/sign/sign.go | 41 | ||||
| -rw-r--r-- | cmd/sigsum-debug/head/verify/verify.go | 9 | ||||
| -rw-r--r-- | cmd/sigsum-debug/key/hash/hash.go | 29 | ||||
| -rw-r--r-- | cmd/sigsum-debug/key/key.go | 51 | ||||
| -rw-r--r-- | cmd/sigsum-debug/key/private/private.go | 29 | ||||
| -rw-r--r-- | cmd/sigsum-debug/key/public/public.go | 32 | ||||
| -rw-r--r-- | cmd/sigsum-debug/leaf/hash/hash.go | 42 | ||||
| -rw-r--r-- | cmd/sigsum-debug/leaf/inclusion/inclusion.go | 9 | ||||
| -rw-r--r-- | cmd/sigsum-debug/leaf/leaf.go | 119 | ||||
| -rw-r--r-- | cmd/sigsum-debug/leaf/sign/sign.go | 37 | ||||
| -rw-r--r-- | cmd/sigsum-debug/leaf/verify/verify.go | 9 | ||||
| -rw-r--r-- | cmd/sigsum-debug/main.go | 65 | 
14 files changed, 584 insertions, 0 deletions
| diff --git a/cmd/sigsum-debug/head/consistency/consistency.go b/cmd/sigsum-debug/head/consistency/consistency.go new file mode 100644 index 0000000..18fbdd6 --- /dev/null +++ b/cmd/sigsum-debug/head/consistency/consistency.go @@ -0,0 +1,9 @@ +package consistency + +import ( +	"fmt" +) + +func Main(args []string, oldSize, newSize uint64, oldRoot, newRoot string) error { +	return fmt.Errorf("TODO") +} diff --git a/cmd/sigsum-debug/head/head.go b/cmd/sigsum-debug/head/head.go new file mode 100644 index 0000000..b1b3044 --- /dev/null +++ b/cmd/sigsum-debug/head/head.go @@ -0,0 +1,103 @@ +package head + +import ( +	"flag" +	"fmt" +	"log" + +	"git.sigsum.org/sigsum-go/cmd/sigsum-debug/head/consistency" +	"git.sigsum.org/sigsum-go/cmd/sigsum-debug/head/sign" +	"git.sigsum.org/sigsum-go/cmd/sigsum-debug/head/verify" +	"git.sigsum.org/sigsum-go/internal/options" +) + +const usage = ` +sigsum-debug head signs and verifies tree heads. + +Usage: + +  sigsum-debug head help +    Outputs a usage message + +  sigsum-debug head sign -k PRIVATE_KEY -h KEY_HASH +    Reads an ascii signed tree head from stdin and outputs a new signature + +  sigsum-debug head verify -k PUBLIC_KEY +    Reads an ascii signed tree head from stdin and verifies it + +  sigsum-debug head consistency -n OLD_SIZE -N NEW_SIZE -r OLD_ROOT -R NEW_ROOT +    Reads an ascii consistency proof from stdin and verifies it + +` + +var ( +	optPrivateKey, optPublicKey, optKeyHash, optOldRoot, optNewRoot string +	optOldSize, optNewSize                                          uint64 +) + +func Main(args []string) error { +	var err error + +	opt := options.New(args, func() { log.Printf(usage[1:]) }, setOptions) +	err = checkOptions(opt.Name()) +	if err == nil { +		switch opt.Name() { +		case "help": +			opt.Usage() +		case "sign": +			err = sign.Main(opt.Args(), optPrivateKey, optKeyHash) +		case "verify": +			err = verify.Main(opt.Args(), optPublicKey) +		case "consistency": +			err = consistency.Main(opt.Args(), optOldSize, optNewSize, optOldRoot, optNewRoot) +		default: +			err = fmt.Errorf("invalid command %q, try \"help\"", opt.Name()) +		} +	} +	if err != nil { +		format := " %s: %w" +		if len(opt.Name()) == 0 { +			format = "%s: %w" +		} +		err = fmt.Errorf(format, opt.Name(), err) +	} + +	return err +} + +func setOptions(fs *flag.FlagSet) { +	switch cmd := fs.Name(); cmd { +	case "help": +	case "sign": +		options.AddString(fs, &optPrivateKey, "k", "private-key", options.DefaultString) +		options.AddString(fs, &optKeyHash, "h", "key-hash", options.DefaultString) +	case "verify": +		options.AddString(fs, &optPublicKey, "k", "public-key", options.DefaultString) +	case "consistency": +		options.AddUint64(fs, &optOldSize, "n", "old-size", options.DefaultUint64) +		options.AddUint64(fs, &optNewSize, "N", "new-size", options.DefaultUint64) +		options.AddString(fs, &optOldRoot, "r", "old-root", options.DefaultString) +		options.AddString(fs, &optNewRoot, "R", "new-root", options.DefaultString) +	} +} + +// checkOptions checks that options with required arguments were set +func checkOptions(cmd string) error { +	var err error + +	switch cmd { +	case "help": +	case "sign": +		err = options.CheckString("private key", optPrivateKey, err) +		err = options.CheckString("key hash", optKeyHash, err) +	case "verify": +		err = options.CheckString("public key", optPublicKey, err) +	case "consistency": +		err = options.CheckUint64("old size", optOldSize, err) +		err = options.CheckUint64("new size", optNewSize, err) +		err = options.CheckString("old root", optOldRoot, err) +		err = options.CheckString("new root", optNewRoot, err) +	} + +	return err +} diff --git a/cmd/sigsum-debug/head/sign/sign.go b/cmd/sigsum-debug/head/sign/sign.go new file mode 100644 index 0000000..572af9a --- /dev/null +++ b/cmd/sigsum-debug/head/sign/sign.go @@ -0,0 +1,41 @@ +package sign + +import ( +	"bytes" +	"fmt" +	"strings" + +	"git.sigsum.org/sigsum-go/internal/fmtio" +	"git.sigsum.org/sigsum-go/pkg/hex" +	"git.sigsum.org/sigsum-go/pkg/types" +) + +func Main(args []string, optPrivateKey, optKeyHash string) error { +	if len(args) != 0 { +		return fmt.Errorf("trailing arguments: %s", strings.Join(args, ", ")) +	} +	b, err := fmtio.BytesFromStdin() +	if err != nil { +		return fmt.Errorf("read stdin: %w", err) +	} +	priv, err := fmtio.SignerFromHex(optPrivateKey) +	if err != nil { +		return fmt.Errorf("parse private key: %v", err) +	} +	keyHash, err := fmtio.KeyHashFromHex(optKeyHash) +	if err != nil { +		return fmt.Errorf("parse key hash: %v", err) +	} + +	var input types.SignedTreeHead +	if err := input.FromASCII(bytes.NewBuffer(b)); err != nil { +		return fmt.Errorf("parse signed tree head: %v", err) +	} +	output, err := input.TreeHead.Sign(priv, &keyHash) +	if err != nil { +		return fmt.Errorf("sign tree head: %v", err) +	} + +	fmt.Printf("%s\n", hex.Serialize(output.Signature[:])) +	return nil +} diff --git a/cmd/sigsum-debug/head/verify/verify.go b/cmd/sigsum-debug/head/verify/verify.go new file mode 100644 index 0000000..69b20aa --- /dev/null +++ b/cmd/sigsum-debug/head/verify/verify.go @@ -0,0 +1,9 @@ +package verify + +import ( +	"fmt" +) + +func Main(args []string, optPublicKey string) error { +	return fmt.Errorf("TODO") +} diff --git a/cmd/sigsum-debug/key/hash/hash.go b/cmd/sigsum-debug/key/hash/hash.go new file mode 100644 index 0000000..0431dfc --- /dev/null +++ b/cmd/sigsum-debug/key/hash/hash.go @@ -0,0 +1,29 @@ +package hash + +import ( +	"fmt" +	"strings" + +	"git.sigsum.org/sigsum-go/internal/fmtio" +	"git.sigsum.org/sigsum-go/pkg/hex" +	"git.sigsum.org/sigsum-go/pkg/types" +) + +func Main(args []string) error { +	if len(args) != 0 { +		return fmt.Errorf("trailing arguments: %s", strings.Join(args, ", ")) +	} +	s, err := fmtio.StringFromStdin() +	if err != nil { +		return fmt.Errorf("read stdin: %w", err) +	} +	pub, err := fmtio.PublicKeyFromHex(s) +	if err != nil { +		return fmt.Errorf("parse key: %w", err) +	} + +	keyHash := types.HashFn(pub[:]) + +	fmt.Printf("%s\n", hex.Serialize(keyHash[:])) +	return nil +} diff --git a/cmd/sigsum-debug/key/key.go b/cmd/sigsum-debug/key/key.go new file mode 100644 index 0000000..88973f2 --- /dev/null +++ b/cmd/sigsum-debug/key/key.go @@ -0,0 +1,51 @@ +package key + +import ( +	"flag" +	"fmt" +	"log" + +	"git.sigsum.org/sigsum-go/cmd/sigsum-debug/key/hash" +	"git.sigsum.org/sigsum-go/cmd/sigsum-debug/key/private" +	"git.sigsum.org/sigsum-go/cmd/sigsum-debug/key/public" +	"git.sigsum.org/sigsum-go/internal/options" +) + +const usage = ` +sigsum-debug key generates private keys, public keys, and key hashes. + +Usage: + +  sigsum-debug key help     Outputs a usage message +  sigsum-debug key private  Outputs a new private key +  sigsum-debug key public   Outputs a public key for a private key on stdin +  sigsum-debug key hash     Outputs a key hash for a public key on stdin + +` + +func Main(args []string) error { +	var err error + +	opt := options.New(args, func() { log.Printf(usage[1:]) }, func(_ *flag.FlagSet) {}) +	switch opt.Name() { +	case "help": +		opt.Usage() +	case "private": +		err = private.Main(opt.Args()) +	case "public": +		err = public.Main(opt.Args()) +	case "hash": +		err = hash.Main(opt.Args()) +	default: +		err = fmt.Errorf("invalid command %q, try \"help\"", opt.Name()) +	} +	if err != nil { +		format := " %s: %w" +		if len(opt.Name()) == 0 { +			format = "%s: %w" +		} +		err = fmt.Errorf(format, opt.Name(), err) +	} + +	return err +} diff --git a/cmd/sigsum-debug/key/private/private.go b/cmd/sigsum-debug/key/private/private.go new file mode 100644 index 0000000..3928f56 --- /dev/null +++ b/cmd/sigsum-debug/key/private/private.go @@ -0,0 +1,29 @@ +package private + +import ( +	"crypto/ed25519" +	"crypto/rand" +	"fmt" +	"strings" + +	"git.sigsum.org/sigsum-go/pkg/hex" +) + +const privateKeySize = 64 + +func Main(args []string) error { +	if len(args) != 0 { +		return fmt.Errorf("trailing arguments: %s", strings.Join(args, ", ")) +	} + +	_, priv, err := ed25519.GenerateKey(rand.Reader) +	if err != nil { +		return fmt.Errorf("generate key: %w", err) +	} +	if len(priv) != privateKeySize { +		return fmt.Errorf("invalid key size %d", len(priv)) +	} + +	fmt.Printf("%s\n", hex.Serialize(priv[:])) +	return nil +} diff --git a/cmd/sigsum-debug/key/public/public.go b/cmd/sigsum-debug/key/public/public.go new file mode 100644 index 0000000..b03d0b9 --- /dev/null +++ b/cmd/sigsum-debug/key/public/public.go @@ -0,0 +1,32 @@ +package public + +import ( +	"crypto/ed25519" +	"fmt" +	"strings" + +	"git.sigsum.org/sigsum-go/internal/fmtio" +	"git.sigsum.org/sigsum-go/pkg/hex" +) + +func Main(args []string) error { +	if len(args) != 0 { +		return fmt.Errorf("trailing arguments: %s", strings.Join(args, ", ")) +	} +	s, err := fmtio.StringFromStdin() +	if err != nil { +		return fmt.Errorf("read stdin: %w", err) +	} + +	priv, err := fmtio.SignerFromHex(s) +	if err != nil { +		return fmt.Errorf("parse key: %w", err) +	} +	pub, ok := priv.Public().(ed25519.PublicKey) +	if !ok { +		return fmt.Errorf("not an ed25519 key") +	} + +	fmt.Printf("%s\n", hex.Serialize(pub[:])) +	return nil +} diff --git a/cmd/sigsum-debug/leaf/hash/hash.go b/cmd/sigsum-debug/leaf/hash/hash.go new file mode 100644 index 0000000..9bc845e --- /dev/null +++ b/cmd/sigsum-debug/leaf/hash/hash.go @@ -0,0 +1,42 @@ +package hash + +import ( +	"fmt" +	"strings" + +	"git.sigsum.org/sigsum-go/internal/fmtio" +	"git.sigsum.org/sigsum-go/pkg/hex" +	"git.sigsum.org/sigsum-go/pkg/types" +) + +func Main(args []string, optKeyHash, optSignature string, optShardHint uint64) error { +	if len(args) != 0 { +		return fmt.Errorf("trailing arguments: %s", strings.Join(args, ", ")) +	} +	data, err := fmtio.BytesFromStdin() +	if err != nil { +		return fmt.Errorf("read stdin: %w", err) +	} +	keyHash, err := fmtio.KeyHashFromHex(optKeyHash) +	if err != nil { +		return fmt.Errorf("parse key hash: %w", err) +	} +	sig, err := fmtio.SignatureFromHex(optSignature) +	if err != nil { +		return fmt.Errorf("parse signature: %w", err) +	} + +	preimage := types.HashFn(data) +	leaf := types.Leaf{ +		Statement: types.Statement{ +			ShardHint: optShardHint, +			Checksum:  *types.HashFn(preimage[:]), +		}, +		Signature: sig, +		KeyHash:   keyHash, +	} +	leafHash := types.LeafHash(leaf.ToBinary()) + +	fmt.Printf("%s\n", hex.Serialize(leafHash[:])) +	return nil +} diff --git a/cmd/sigsum-debug/leaf/inclusion/inclusion.go b/cmd/sigsum-debug/leaf/inclusion/inclusion.go new file mode 100644 index 0000000..f9aeb68 --- /dev/null +++ b/cmd/sigsum-debug/leaf/inclusion/inclusion.go @@ -0,0 +1,9 @@ +package inclusion + +import ( +	"fmt" +) + +func Main(args []string, optLeafHash, optRootHash string, optTreeSize uint64) error { +	return fmt.Errorf("TODO") +} diff --git a/cmd/sigsum-debug/leaf/leaf.go b/cmd/sigsum-debug/leaf/leaf.go new file mode 100644 index 0000000..97de37e --- /dev/null +++ b/cmd/sigsum-debug/leaf/leaf.go @@ -0,0 +1,119 @@ +package leaf + +import ( +	"flag" +	"fmt" +	"log" + +	"git.sigsum.org/sigsum-go/cmd/sigsum-debug/leaf/hash" +	"git.sigsum.org/sigsum-go/cmd/sigsum-debug/leaf/inclusion" +	"git.sigsum.org/sigsum-go/cmd/sigsum-debug/leaf/sign" +	"git.sigsum.org/sigsum-go/cmd/sigsum-debug/leaf/verify" +	"git.sigsum.org/sigsum-go/internal/options" +) + +const usage = ` +sigsum-debug leaf signs, verifies, and hashes Merkle tree leaves. + +Usage: + +  sigsum-debug leaf help +    Outputs a usage message + +  sigsum-debug leaf sign -k PRIVATE_KEY -h SHARD_HINT +    Reads data from stdin and outputs a signature + +  sigsum-debug leaf verify -k PUBLIC_KEY -s SIGNATURE -h SHARD_HINT +    Reads data from stdin and verifies its signature + +  sigsum-debug leaf hash -k KEY_HASH -s SIGNATURE -h SHARD_HINT +    Reads data from stdin and outputs a leaf hash + +  sigsum-debug leaf inclusion -l LEAF_HASH -n TREE_SIZE -r ROOT_HASH +    Reads an inclusion proof from stdin and verifies it + +` + +var ( +	optPrivateKey, optPublicKey, optKeyHash, optLeafHash, optRootHash, optSignature string +	optShardHint, optTreeSize                                                       uint64 +) + +func Main(args []string) error { +	var err error + +	opt := options.New(args, func() { log.Printf(usage[1:]) }, setOptions) +	err = checkOptions(opt.Name()) +	if err == nil { +		switch opt.Name() { +		case "help": +			opt.Usage() +		case "sign": +			err = sign.Main(opt.Args(), optPrivateKey, optShardHint) +		case "verify": +			err = verify.Main(opt.Args(), optPublicKey, optSignature, optShardHint) +		case "hash": +			err = hash.Main(opt.Args(), optKeyHash, optSignature, optShardHint) +		case "inclusion": +			err = inclusion.Main(opt.Args(), optLeafHash, optRootHash, optTreeSize) +		default: +			err = fmt.Errorf("invalid command %q, try \"help\"", opt.Name()) +		} +	} +	if err != nil { +		format := " %s: %w" +		if len(opt.Name()) == 0 { +			format = "%s: %w" +		} +		err = fmt.Errorf(format, opt.Name(), err) +	} + +	return err +} + +func setOptions(fs *flag.FlagSet) { +	switch cmd := fs.Name(); cmd { +	case "help": +	case "sign": +		options.AddString(fs, &optPrivateKey, "k", "private-key", options.DefaultString) +		options.AddUint64(fs, &optShardHint, "h", "shard-hint", options.DefaultUint64) +	case "verify": +		options.AddString(fs, &optPublicKey, "k", "public-key", options.DefaultString) +		options.AddString(fs, &optSignature, "s", "signature", options.DefaultString) +		options.AddUint64(fs, &optShardHint, "h", "shard-hint", options.DefaultUint64) +	case "hash": +		options.AddString(fs, &optKeyHash, "k", "key-hash", options.DefaultString) +		options.AddString(fs, &optSignature, "s", "signature", options.DefaultString) +		options.AddUint64(fs, &optShardHint, "h", "shard-hint", options.DefaultUint64) +	case "inclusion": +		options.AddString(fs, &optLeafHash, "l", "leaf-hash", options.DefaultString) +		options.AddUint64(fs, &optTreeSize, "n", "tree-size", options.DefaultUint64) +		options.AddString(fs, &optRootHash, "r", "root-hash", options.DefaultString) +	} +} + +// checkOptions checks that options with required arguments were set +func checkOptions(cmd string) error { +	var err error + +	switch cmd { +	case "help": +	case "sign": +		err = options.CheckString("private key", optPrivateKey, err) +		err = options.CheckUint64("shard hint", optShardHint, err) +	case "verify": +		err = options.CheckString("public key", optPublicKey, err) +		err = options.CheckString("signature", optSignature, err) +		err = options.CheckUint64("shard hint", optShardHint, err) +	case "hash": +		err = options.CheckString("key hash", optKeyHash, err) +		err = options.CheckString("signature", optSignature, err) +		err = options.CheckUint64("shard hint", optShardHint, err) +	case "inclusion": +		err = options.CheckString("leaf hash", optLeafHash, err) +		err = options.CheckUint64("tree size", optTreeSize, err) +		err = options.CheckString("root hash", optRootHash, err) +	} + +	return err +} diff --git a/cmd/sigsum-debug/leaf/sign/sign.go b/cmd/sigsum-debug/leaf/sign/sign.go new file mode 100644 index 0000000..348ae23 --- /dev/null +++ b/cmd/sigsum-debug/leaf/sign/sign.go @@ -0,0 +1,37 @@ +package sign + +import ( +	"fmt" +	"strings" + +	"git.sigsum.org/sigsum-go/internal/fmtio" +	"git.sigsum.org/sigsum-go/pkg/hex" +	"git.sigsum.org/sigsum-go/pkg/types" +) + +func Main(args []string, optPrivateKey string, optShardHint uint64) error { +	if len(args) != 0 { +		return fmt.Errorf("trailing arguments: %s", strings.Join(args, ", ")) +	} +	data, err := fmtio.BytesFromStdin() +	if err != nil { +		return fmt.Errorf("read stdin: %w", err) +	} +	priv, err := fmtio.SignerFromHex(optPrivateKey) +	if err != nil { +		return fmt.Errorf("parse private key: %w", err) +	} + +	preimage := types.HashFn(data) +	stm := types.Statement{ +		ShardHint: optShardHint, +		Checksum:  *types.HashFn(preimage[:]), +	} +	sig, err := stm.Sign(priv) +	if err != nil { +		fmt.Errorf("sign leaf: %w", err) +	} + +	fmt.Printf("%s\n", hex.Serialize(sig[:])) +	return nil +} diff --git a/cmd/sigsum-debug/leaf/verify/verify.go b/cmd/sigsum-debug/leaf/verify/verify.go new file mode 100644 index 0000000..a00791a --- /dev/null +++ b/cmd/sigsum-debug/leaf/verify/verify.go @@ -0,0 +1,9 @@ +package verify + +import ( +	"fmt" +) + +func Main(args []string, optPublicKey, optSignature string, optShardHint uint64) error { +	return fmt.Errorf("TODO") +} diff --git a/cmd/sigsum-debug/main.go b/cmd/sigsum-debug/main.go new file mode 100644 index 0000000..7a1c894 --- /dev/null +++ b/cmd/sigsum-debug/main.go @@ -0,0 +1,65 @@ +// package main provides a tool named sigsum-debug +// +// Install: +// +//     $ go install git.sigsum.org/sigsum-go/cmd/sigsum-debug@latest +// +// Usage: +// +//     $ sigsum-debug help +// +package main + +import ( +	"flag" +	"fmt" +	"log" +	"os" + +	"git.sigsum.org/sigsum-go/cmd/sigsum-debug/head" +	"git.sigsum.org/sigsum-go/cmd/sigsum-debug/key" +	"git.sigsum.org/sigsum-go/cmd/sigsum-debug/leaf" +	"git.sigsum.org/sigsum-go/internal/options" +) + +const usage = ` +sigsum-debug is a tool that helps debug sigsum logs on the command-line. +It is meant to be used in conjuction with other utilities such as curl. + +Usage: + +  sigsum-debug help  Usage message +  sigsum-debug key   Private and public key utilities +  sigsum-debug leaf  Hash, sign, and verify tree leaves +  sigsum-debug head  Sign and verify tree heads + +` + +func main() { +	var err error + +	log.SetFlags(0) +	opt := options.New(os.Args[1:], func() { log.Printf(usage[1:]) }, func(_ *flag.FlagSet) {}) +	switch opt.Name() { +	case "help": +		opt.Usage() +	case "key": +		err = key.Main(opt.Args()) +	case "leaf": +		err = leaf.Main(opt.Args()) +	case "head": +		err = head.Main(opt.Args()) +	default: +		err = fmt.Errorf(": invalid command %q, try \"help\"", opt.Name()) +	} + +	if err != nil { +		format := "sigsum-debug %s%s" +		if len(opt.Name()) == 0 { +			format = "sigsum-debug%s%s" +		} + +		log.Printf(format, opt.Name(), err.Error()) +		os.Exit(1) +	} +} | 
