forked from TrueCloudLab/frostfs-api-go
[#3] signature: Verify parts in parallel
Verify request/response parts in parallel Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
This commit is contained in:
parent
611f73ad0f
commit
73fde0e37c
4 changed files with 54 additions and 43 deletions
4
go.mod
4
go.mod
|
@ -5,7 +5,7 @@ go 1.18
|
||||||
require (
|
require (
|
||||||
git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0
|
git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0
|
||||||
github.com/stretchr/testify v1.7.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/grpc v1.48.0
|
||||||
google.golang.org/protobuf v1.28.0
|
google.golang.org/protobuf v1.28.0
|
||||||
)
|
)
|
||||||
|
@ -14,10 +14,10 @@ require (
|
||||||
git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 // indirect
|
git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.0 // indirect
|
github.com/davecgh/go-spew v1.1.0 // indirect
|
||||||
github.com/golang/protobuf v1.5.2 // 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/mr-tron/base58 v1.2.0 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974 // 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/sys v0.1.0 // indirect
|
||||||
golang.org/x/text v0.3.3 // indirect
|
golang.org/x/text v0.3.3 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect
|
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect
|
||||||
|
|
3
go.sum
3
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.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.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 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/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/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=
|
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-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
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-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-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-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
|
|
@ -6,8 +6,8 @@ import (
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
"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/session"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/collection"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/signature"
|
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/signature"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
)
|
)
|
||||||
|
|
||||||
type signatureProvider interface {
|
type signatureProvider interface {
|
||||||
|
@ -16,6 +16,12 @@ type signatureProvider interface {
|
||||||
GetOriginSignature() *refs.Signature
|
GetOriginSignature() *refs.Signature
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type buffers struct {
|
||||||
|
Body []byte
|
||||||
|
Meta []byte
|
||||||
|
Header []byte
|
||||||
|
}
|
||||||
|
|
||||||
// VerifyServiceMessage verifies service message.
|
// VerifyServiceMessage verifies service message.
|
||||||
func VerifyServiceMessage(msg interface{}) error {
|
func VerifyServiceMessage(msg interface{}) error {
|
||||||
switch v := msg.(type) {
|
switch v := msg.(type) {
|
||||||
|
@ -34,16 +40,23 @@ func verifyServiceRequest(v serviceRequest) error {
|
||||||
meta := v.GetMetaHeader()
|
meta := v.GetMetaHeader()
|
||||||
verificationHeader := v.GetVerificationHeader()
|
verificationHeader := v.GetVerificationHeader()
|
||||||
body := serviceMessageBody(v)
|
body := serviceMessageBody(v)
|
||||||
size := collection.Max(body.StableSize(), meta.StableSize(), verificationHeader.StableSize())
|
buffers := createBuffers(body.StableSize(), meta.StableSize(), verificationHeader.StableSize())
|
||||||
buf := make([]byte, 0, size)
|
return verifyServiceRequestRecursive(body, meta, verificationHeader, buffers)
|
||||||
return verifyServiceRequestRecursive(body, meta, verificationHeader, buf)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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()
|
verificationHeaderOrigin := verify.GetOrigin()
|
||||||
metaOrigin := meta.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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -51,23 +64,40 @@ func verifyServiceRequestRecursive(body stableMarshaler, meta *session.RequestMe
|
||||||
return nil
|
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) {
|
func verifyMessageParts(body, meta, originHeader stableMarshaler, hasOriginHeader bool, sigProvider signatureProvider, buffers *buffers) (stop bool, err error) {
|
||||||
if err := verifyServiceMessagePart(meta, sigProvider.GetMetaSignature, buf); err != nil {
|
eg := &errgroup.Group{}
|
||||||
return false, fmt.Errorf("could not verify meta header: %w", err)
|
|
||||||
|
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 {
|
if err := eg.Wait(); err != nil {
|
||||||
return false, fmt.Errorf("could not verify origin of verification header: %w", err)
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !hasOriginHeader {
|
if !hasOriginHeader {
|
||||||
if err := verifyServiceMessagePart(body, sigProvider.GetBodySignature, buf); err != nil {
|
|
||||||
return false, fmt.Errorf("could not verify body: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,16 +112,15 @@ func verifyServiceResponse(v serviceResponse) error {
|
||||||
meta := v.GetMetaHeader()
|
meta := v.GetMetaHeader()
|
||||||
verificationHeader := v.GetVerificationHeader()
|
verificationHeader := v.GetVerificationHeader()
|
||||||
body := serviceMessageBody(v)
|
body := serviceMessageBody(v)
|
||||||
size := collection.Max(body.StableSize(), meta.StableSize(), verificationHeader.StableSize())
|
buffers := createBuffers(body.StableSize(), meta.StableSize(), verificationHeader.StableSize())
|
||||||
buf := make([]byte, 0, size)
|
return verifyServiceResponseRecursive(body, meta, verificationHeader, buffers)
|
||||||
return verifyServiceResponseRecursive(body, meta, verificationHeader, buf)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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()
|
verificationHeaderOrigin := verify.GetOrigin()
|
||||||
metaOrigin := meta.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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -99,7 +128,7 @@ func verifyServiceResponseRecursive(body stableMarshaler, meta *session.Response
|
||||||
return nil
|
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 {
|
func verifyServiceMessagePart(part stableMarshaler, sigRdr func() *refs.Signature, buf []byte) error {
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
|
Loading…
Reference in a new issue