aboutsummaryrefslogtreecommitdiff
path: root/cmd/sigsum/cmd.go
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/sigsum/cmd.go')
-rw-r--r--cmd/sigsum/cmd.go131
1 files changed, 131 insertions, 0 deletions
diff --git a/cmd/sigsum/cmd.go b/cmd/sigsum/cmd.go
new file mode 100644
index 0000000..70a1c51
--- /dev/null
+++ b/cmd/sigsum/cmd.go
@@ -0,0 +1,131 @@
+package main
+
+import (
+ "bytes"
+ "context"
+ "fmt"
+ "io/ioutil"
+ "time"
+
+ "git.sigsum.org/sigsum-lib-go/pkg/requests"
+ "git.sigsum.org/sigsum-lib-go/pkg/types"
+ "git.sigsum.org/sigsum-tool-go/pkg/client"
+ "git.sigsum.org/sigsum-tool-go/pkg/policy"
+ "git.sigsum.org/sigsum-tool-go/pkg/signatures"
+ "git.sigsum.org/sigsum-tool-go/pkg/signatures/minisign"
+ "git.sigsum.org/sigsum-tool-go/pkg/signatures/signify"
+ "git.sigsum.org/sigsum-tool-go/pkg/signatures/ssh"
+)
+
+func cmdVerify(args []string, policy policy.Policy, optVerifyType, optVerifyKey string) error {
+ return fmt.Errorf("TODO")
+}
+
+func cmdBundle(args []string, policy policy.Policy, optBundleType, optBundleKey, optBundleDomainHint string) error {
+ if len(args) == 0 {
+ return fmt.Errorf("bundle: need at least one file")
+ }
+
+ var parser signatures.Parser
+ switch optBundleType {
+ case "signify":
+ parser = &signify.Parser{}
+ case "minisign":
+ parser = &minisign.Parser{}
+ case "ssh":
+ parser = &ssh.Parser{}
+ default:
+ return fmt.Errorf("bundle: invalid key type %q", optBundleType)
+ }
+
+ b, err := ioutil.ReadFile(optBundleKey)
+ if err != nil {
+ return fmt.Errorf("bundle: failed reading file %q: %v", optBundleKey, err)
+ }
+ pub, err := parser.PublicKey(bytes.NewBuffer(b))
+ if err != nil {
+ return fmt.Errorf("bundle: %v", err)
+ }
+ // TODO: check that domain hint is valid for public key
+
+ var reqs []requests.Leaf
+ for _, path := range args {
+ checksum, err := fileHash(path)
+ if err != nil {
+ return fmt.Errorf("bundle: %v", err)
+ }
+
+ sigPath := path + parser.SignatureSuffix()
+ b, err := ioutil.ReadFile(sigPath)
+ if err != nil {
+ return fmt.Errorf("bundle: failed reading file %q: %v", sigPath, err)
+ }
+ sig, err := parser.Signature(bytes.NewBuffer(b))
+ if err != nil {
+ return fmt.Errorf("bundle: %v", err)
+ }
+
+ req := requests.Leaf{
+ Statement: types.Statement{
+ ShardHint: policy.ShardHint(),
+ Checksum: *checksum,
+ },
+ Signature: *sig,
+ VerificationKey: *pub,
+ DomainHint: optBundleDomainHint,
+ }
+ if !req.Statement.Verify(&req.VerificationKey, &req.Signature) {
+ return fmt.Errorf("bundle: invalid signature for file %q", path)
+ }
+ reqs = append(reqs, req)
+ }
+
+ sc := client.NewSubmitClient(policy)
+ ctx, cancel := context.WithTimeout(context.Background(), 15*time.Minute)
+ defer cancel()
+ bundles, err := sc.AddLeaves(ctx, reqs)
+ if err != nil {
+ return fmt.Errorf("bundle: %v", err)
+ }
+
+ // TODO: verify bundles
+ // TODO: write to files
+ fmt.Printf("got %d bundles\n", len(bundles))
+ return nil
+}
+
+func cmdFormat(args []string, policy policy.Policy) error {
+ if len(args) != 1 {
+ return fmt.Errorf("format: need exactly one file")
+ }
+
+ checksum, err := fileHash(args[0])
+ if err != nil {
+ return fmt.Errorf("format: %v", err)
+ }
+ stm := types.Statement{
+ ShardHint: policy.ShardHint(),
+ Checksum: *checksum,
+ }
+
+ fmt.Printf("%s", stm.ToBinary())
+ return nil
+}
+
+func cmdNamespace(args []string, policy policy.Policy) error {
+ if len(args) != 0 {
+ return fmt.Errorf("namespace: got trailing arguments")
+ }
+
+ fmt.Printf("tree_leaf:v0:%d@sigsum.org", policy.ShardHint())
+ return nil
+}
+
+// TODO: don't read full file into memory at once
+func fileHash(path string) (*types.Hash, error) {
+ b, err := ioutil.ReadFile(path)
+ if err != nil {
+ return nil, fmt.Errorf("failed reading file %q", path)
+ }
+ return types.HashFn(b), nil
+}