From 73fde0e37cdd264bbd3244464d02c1f247ead14b Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 28 Feb 2023 18:52:50 +0300 Subject: [PATCH] [#3] signature: Verify parts in parallel Verify request/response parts in parallel Signed-off-by: Dmitrii Stepanov --- go.mod | 4 +-- go.sum | 3 +- signature/verify.go | 73 ++++++++++++++++++++++++++++------------ util/collection/slice.go | 17 ---------- 4 files changed, 54 insertions(+), 43 deletions(-) delete mode 100644 util/collection/slice.go diff --git a/go.mod b/go.mod index fd9049e..6fce011 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 github.com/stretchr/testify v1.7.0 - golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 + golang.org/x/sync v0.1.0 google.golang.org/grpc v1.48.0 google.golang.org/protobuf v1.28.0 ) @@ -14,10 +14,10 @@ require ( git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 // indirect github.com/davecgh/go-spew v1.1.0 // indirect github.com/golang/protobuf v1.5.2 // indirect + github.com/google/go-cmp v0.5.8 // indirect github.com/mr-tron/base58 v1.2.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect golang.org/x/net v0.0.0-20201021035429-f5854403a974 // indirect - golang.org/x/sync v0.1.0 // indirect golang.org/x/sys v0.1.0 // indirect golang.org/x/text v0.3.3 // indirect google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect diff --git a/go.sum b/go.sum index 4224bda..e81a6ec 100644 --- a/go.sum +++ b/go.sum @@ -48,6 +48,7 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= @@ -64,8 +65,6 @@ go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqe golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 h1:Jvc7gsqn21cJHCmAWx0LiimpP18LZmUxkT5Mp7EZ1mI= -golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= diff --git a/signature/verify.go b/signature/verify.go index fe76844..08f91d9 100644 --- a/signature/verify.go +++ b/signature/verify.go @@ -6,8 +6,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/collection" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/signature" + "golang.org/x/sync/errgroup" ) type signatureProvider interface { @@ -16,6 +16,12 @@ type signatureProvider interface { GetOriginSignature() *refs.Signature } +type buffers struct { + Body []byte + Meta []byte + Header []byte +} + // VerifyServiceMessage verifies service message. func VerifyServiceMessage(msg interface{}) error { switch v := msg.(type) { @@ -34,16 +40,23 @@ func verifyServiceRequest(v serviceRequest) error { meta := v.GetMetaHeader() verificationHeader := v.GetVerificationHeader() body := serviceMessageBody(v) - size := collection.Max(body.StableSize(), meta.StableSize(), verificationHeader.StableSize()) - buf := make([]byte, 0, size) - return verifyServiceRequestRecursive(body, meta, verificationHeader, buf) + buffers := createBuffers(body.StableSize(), meta.StableSize(), verificationHeader.StableSize()) + return verifyServiceRequestRecursive(body, meta, verificationHeader, buffers) } -func verifyServiceRequestRecursive(body stableMarshaler, meta *session.RequestMetaHeader, verify *session.RequestVerificationHeader, buf []byte) error { +func createBuffers(bodySize, metaSize, headerSize int) *buffers { + return &buffers{ + Body: make([]byte, 0, bodySize), + Meta: make([]byte, 0, metaSize), + Header: make([]byte, 0, headerSize), + } +} + +func verifyServiceRequestRecursive(body stableMarshaler, meta *session.RequestMetaHeader, verify *session.RequestVerificationHeader, buffers *buffers) error { verificationHeaderOrigin := verify.GetOrigin() metaOrigin := meta.GetOrigin() - stop, err := verifyMessageParts(body, meta, verificationHeaderOrigin, verificationHeaderOrigin != nil, verify, buf) + stop, err := verifyMessageParts(body, meta, verificationHeaderOrigin, verificationHeaderOrigin != nil, verify, buffers) if err != nil { return err } @@ -51,23 +64,40 @@ func verifyServiceRequestRecursive(body stableMarshaler, meta *session.RequestMe return nil } - return verifyServiceRequestRecursive(body, metaOrigin, verificationHeaderOrigin, buf) + return verifyServiceRequestRecursive(body, metaOrigin, verificationHeaderOrigin, buffers) } -func verifyMessageParts(body, meta, originHeader stableMarshaler, hasOriginHeader bool, sigProvider signatureProvider, buf []byte) (stop bool, err error) { - if err := verifyServiceMessagePart(meta, sigProvider.GetMetaSignature, buf); err != nil { - return false, fmt.Errorf("could not verify meta header: %w", err) +func verifyMessageParts(body, meta, originHeader stableMarshaler, hasOriginHeader bool, sigProvider signatureProvider, buffers *buffers) (stop bool, err error) { + eg := &errgroup.Group{} + + eg.Go(func() error { + if err := verifyServiceMessagePart(meta, sigProvider.GetMetaSignature, buffers.Meta); err != nil { + return fmt.Errorf("could not verify meta header: %w", err) + } + return nil + }) + + eg.Go(func() error { + if err := verifyServiceMessagePart(originHeader, sigProvider.GetOriginSignature, buffers.Header); err != nil { + return fmt.Errorf("could not verify origin of verification header: %w", err) + } + return nil + }) + + if !hasOriginHeader { + eg.Go(func() error { + if err := verifyServiceMessagePart(body, sigProvider.GetBodySignature, buffers.Body); err != nil { + return fmt.Errorf("could not verify body: %w", err) + } + return nil + }) } - if err := verifyServiceMessagePart(originHeader, sigProvider.GetOriginSignature, buf); err != nil { - return false, fmt.Errorf("could not verify origin of verification header: %w", err) + if err := eg.Wait(); err != nil { + return false, err } if !hasOriginHeader { - if err := verifyServiceMessagePart(body, sigProvider.GetBodySignature, buf); err != nil { - return false, fmt.Errorf("could not verify body: %w", err) - } - return true, nil } @@ -82,16 +112,15 @@ func verifyServiceResponse(v serviceResponse) error { meta := v.GetMetaHeader() verificationHeader := v.GetVerificationHeader() body := serviceMessageBody(v) - size := collection.Max(body.StableSize(), meta.StableSize(), verificationHeader.StableSize()) - buf := make([]byte, 0, size) - return verifyServiceResponseRecursive(body, meta, verificationHeader, buf) + buffers := createBuffers(body.StableSize(), meta.StableSize(), verificationHeader.StableSize()) + return verifyServiceResponseRecursive(body, meta, verificationHeader, buffers) } -func verifyServiceResponseRecursive(body stableMarshaler, meta *session.ResponseMetaHeader, verify *session.ResponseVerificationHeader, buf []byte) error { +func verifyServiceResponseRecursive(body stableMarshaler, meta *session.ResponseMetaHeader, verify *session.ResponseVerificationHeader, buffers *buffers) error { verificationHeaderOrigin := verify.GetOrigin() metaOrigin := meta.GetOrigin() - stop, err := verifyMessageParts(body, meta, verificationHeaderOrigin, verificationHeaderOrigin != nil, verify, buf) + stop, err := verifyMessageParts(body, meta, verificationHeaderOrigin, verificationHeaderOrigin != nil, verify, buffers) if err != nil { return err } @@ -99,7 +128,7 @@ func verifyServiceResponseRecursive(body stableMarshaler, meta *session.Response return nil } - return verifyServiceResponseRecursive(body, metaOrigin, verificationHeaderOrigin, buf) + return verifyServiceResponseRecursive(body, metaOrigin, verificationHeaderOrigin, buffers) } func verifyServiceMessagePart(part stableMarshaler, sigRdr func() *refs.Signature, buf []byte) error { diff --git a/util/collection/slice.go b/util/collection/slice.go deleted file mode 100644 index 436f28c..0000000 --- a/util/collection/slice.go +++ /dev/null @@ -1,17 +0,0 @@ -package collection - -import "golang.org/x/exp/constraints" - -// Max finds maximum value of items. -func Max[T constraints.Ordered](items ...T) T { - if len(items) == 0 { - panic("failed to get max value: empty slice") - } - result := items[0] - for i := 1; i < len(items); i++ { - if items[i] > result { - result = items[i] - } - } - return result -}