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) }