aboutsummaryrefslogtreecommitdiff
path: root/cmd/sigsum/bundle
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/sigsum/bundle')
-rw-r--r--cmd/sigsum/bundle/bundle.go98
1 files changed, 98 insertions, 0 deletions
diff --git a/cmd/sigsum/bundle/bundle.go b/cmd/sigsum/bundle/bundle.go
new file mode 100644
index 0000000..d0ce207
--- /dev/null
+++ b/cmd/sigsum/bundle/bundle.go
@@ -0,0 +1,98 @@
+package bundle
+
+import (
+ "bytes"
+ "context"
+ "fmt"
+ "io/ioutil"
+ "time"
+
+ "git.sigsum.org/sigsum-go/pkg/requests"
+ "git.sigsum.org/sigsum-go/pkg/types"
+ "git.sigsum.org/sigsum-tools-go/internal/util"
+ "git.sigsum.org/sigsum-tools-go/pkg/client"
+ "git.sigsum.org/sigsum-tools-go/pkg/policy"
+ "git.sigsum.org/sigsum-tools-go/pkg/signatures"
+ "git.sigsum.org/sigsum-tools-go/pkg/signatures/minisign"
+ "git.sigsum.org/sigsum-tools-go/pkg/signatures/signify"
+ "git.sigsum.org/sigsum-tools-go/pkg/signatures/ssh"
+)
+
+func Main(args []string, policy policy.Policy, optType, optKey, optDomainHint string) error {
+ if len(args) == 0 {
+ return fmt.Errorf("bundle: need at least one input file")
+ }
+ b, err := ioutil.ReadFile(optKey)
+ if err != nil {
+ return fmt.Errorf("bundle: read key %q: %v", optKey, err)
+ }
+ parser, err := signatureParser(optType)
+ if err != nil {
+ return fmt.Errorf("bundle: %v", 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 {
+ preimage, err := util.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{
+ ShardHint: policy.ShardHint(),
+ Preimage: *preimage,
+ Signature: *sig,
+ VerificationKey: *pub,
+ DomainHint: optDomainHint,
+ }
+
+ sd := types.Statement{
+ ShardHint: req.ShardHint,
+ Checksum: *types.HashFn(req.Preimage[:]),
+ }
+ if !sd.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 signatureParser(optType string) (signatures.Parser, error) {
+ switch optType {
+ case "signify":
+ return &signify.Parser{}, nil
+ case "minisign":
+ return &minisign.Parser{}, nil
+ case "ssh":
+ return &ssh.Parser{}, nil
+ }
+ return nil, fmt.Errorf("invalid key type %q", optType)
+}