package service import ( "context" "io" "github.com/keys-pub/keys/saltpack" "github.com/pkg/errors" "google.golang.org/grpc" ) // Verify (RPC) ... func (s *service) Verify(ctx context.Context, req *VerifyRequest) (*VerifyResponse, error) { verified, kid, err := saltpack.Verify(req.Data) if err != nil { return nil, err } var signer *Key if kid != "" { s, err := s.verifyKey(ctx, kid) if err != nil { return nil, err } signer = s // If we don't have the key saved, don't include the user information. if !signer.Saved { signer.User = nil } } return &VerifyResponse{Data: verified, Signer: signer}, nil } // VerifyDetached (RPC) ... func (s *service) VerifyDetached(ctx context.Context, req *VerifyDetachedRequest) (*VerifyDetachedResponse, error) { kid, err := saltpack.VerifyDetached(req.Sig, req.Data) if err != nil { return nil, err } var signer *Key if kid != "" { s, err := s.verifyKey(ctx, kid) if err != nil { return nil, err } signer = s } return &VerifyDetachedResponse{Signer: signer}, nil } // VerifyFile (RPC) ... func (s *service) VerifyFile(srv RPC_VerifyFileServer) error { req, err := srv.Recv() if err != nil { return err } if req.In == "" { return errors.Errorf("in not specified") } out, err := resolveOutPath(req.Out, req.In, ".signed") if err != nil { return err } signer, err := s.verifyWriteInOut(srv.Context(), req.In, out) if err != nil { return err } if err := srv.Send(&VerifyFileOutput{ Signer: signer, Out: out, }); err != nil { return err } // if err := srv.SendAndClose(&VerifyFileOutput{ // Signer: signer, // Out: out, // }); err != nil { // return err // } return nil } // VerifyDetachedFile (RPC) ... func (s *service) VerifyDetachedFile(srv RPC_VerifyDetachedFileServer) error { req, err := srv.Recv() if err != nil { return err } in := req.In if in == "" { return errors.Errorf("in not specified") } signer, err := s.verifyDetachedIn(srv.Context(), req.Sig, in) if err != nil { return err } resp := &VerifyDetachedResponse{ Signer: signer, } return srv.SendAndClose(resp) } // VerifyStream (RPC) ... func (s *service) VerifyStream(srv RPC_VerifyStreamServer) error { return s.verifyStream(srv, false) } type verifyStreamServer interface { Send(*VerifyOutput) error Recv() (*VerifyInput, error) grpc.ServerStream } func (s *service) verifyStream(srv verifyStreamServer, armored bool) error { recvFn := func() ([]byte, error) { req, recvErr := srv.Recv() if recvErr != nil { return nil, recvErr } return req.Data, nil } reader := newStreamReader(srv.Context(), recvFn) streamReader, kid, err := saltpack.NewVerifyStream(reader) if err != nil { return errors.Wrapf(err, "faild to verify stream") } var signer *Key if kid != "" { s, err := s.verifyKey(srv.Context(), kid) if err != nil { return err } signer = s } sendFn := func(b []byte, signer *Key) error { resp := VerifyOutput{ Data: b, Signer: signer, } return srv.Send(&resp) } if err := s.readFromStream(srv.Context(), streamReader, signer, sendFn); err != nil { return errors.Wrapf(err, "failed to read from verify stream") } return nil } // VerifyDetachedStream (RPC) ... func (s *service) VerifyDetachedStream(srv RPC_VerifyDetachedStreamServer) error { ctx := srv.Context() first, err := srv.Recv() if err != nil { return err } recvFn := func() ([]byte, error) { req, recvErr := srv.Recv() if recvErr != nil { return nil, recvErr } return req.Data, nil } reader := newStreamReader(srv.Context(), recvFn) if err := reader.write(first.Data); err != nil { return err } kid, err := saltpack.VerifyDetachedReader(first.Sig, reader) if err != nil { return err } var signer *Key if kid != "" { s, err := s.verifyKey(ctx, kid) if err != nil { return err } signer = s } resp := &VerifyDetachedResponse{ Signer: signer, } return srv.SendAndClose(resp) } // VerifyStreamClient ... type VerifyStreamClient interface { Send(*VerifyInput) error Recv() (*VerifyOutput, error) grpc.ClientStream } // NewVerifyStreamClient ... func NewVerifyStreamClient(ctx context.Context, cl RPCClient) (VerifyStreamClient, error) { return cl.VerifyStream(ctx) } func (s *service) readFromStream(ctx context.Context, streamReader io.Reader, signer *Key, sendFn func(b []byte, signer *Key) error) error { buf := make([]byte, 1024*1024) for { select { case <-ctx.Done(): return ctx.Err() default: } n, err := streamReader.Read(buf) if n != 0 { if err := sendFn(buf[:n], signer); err != nil { return err } } if err != nil { if err == io.EOF { // Send empty bytes denotes EOF if err := sendFn([]byte{}, signer); err != nil { return err } break } return err } } return nil } func (s *service) verifyWriteInOut(ctx context.Context, in string, out string) (*Key, error) { kid, err := saltpack.VerifyFile(in, out) if err != nil { return nil, err } var signer *Key if kid != "" { s, err := s.verifyKey(ctx, kid) if err != nil { return nil, err } signer = s } return signer, nil } func (s *service) verifyDetachedIn(ctx context.Context, sig []byte, in string) (*Key, error) { logger.Infof("Verify (detached) %s", in) kid, err := saltpack.VerifyFileDetached(sig, in) if err != nil { return nil, err } var signer *Key if kid != "" { s, err := s.verifyKey(ctx, kid) if err != nil { return nil, err } signer = s } return signer, nil }