Refactor sign/verify message #6
8 changed files with 399 additions and 334 deletions
2
.github/workflows/go.yml
vendored
2
.github/workflows/go.yml
vendored
|
@ -17,7 +17,7 @@ jobs:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
go: [ '1.17.x', '1.18.x', '1.19.x' ]
|
go: [ '1.18.x', '1.19.x', '1.20.x' ]
|
||||||
steps:
|
steps:
|
||||||
- name: Setup go
|
- name: Setup go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v3
|
||||||
|
|
6
go.mod
6
go.mod
|
@ -1,10 +1,11 @@
|
||||||
module github.com/TrueCloudLab/frostfs-api-go/v2
|
module github.com/TrueCloudLab/frostfs-api-go/v2
|
||||||
|
|
||||||
go 1.17
|
go 1.18
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/TrueCloudLab/frostfs-crypto v0.5.0
|
github.com/TrueCloudLab/frostfs-crypto v0.5.0
|
||||||
github.com/stretchr/testify v1.7.0
|
github.com/stretchr/testify v1.7.0
|
||||||
|
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
|
||||||
)
|
)
|
||||||
|
@ -13,10 +14,11 @@ require (
|
||||||
github.com/TrueCloudLab/rfc6979 v0.3.0 // indirect
|
github.com/TrueCloudLab/rfc6979 v0.3.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/sys v0.0.0-20210119212857-b64e53b001e4 // 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
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
|
||||||
|
|
9
go.sum
9
go.sum
|
@ -46,8 +46,9 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
|
||||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.0/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.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
|
|
||||||
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/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=
|
||||||
|
@ -82,13 +83,16 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||||
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4 h1:myAQVi0cGEoqQVR5POX+8RR2mrocKqNN1hmeMqhX27k=
|
|
||||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
|
||||||
|
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
@ -98,7 +102,6 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3
|
||||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
|
|
115
signature/body.go
Normal file
115
signature/body.go
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
package signature
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/TrueCloudLab/frostfs-api-go/v2/accounting"
|
||||||
|
"github.com/TrueCloudLab/frostfs-api-go/v2/container"
|
||||||
|
"github.com/TrueCloudLab/frostfs-api-go/v2/netmap"
|
||||||
|
"github.com/TrueCloudLab/frostfs-api-go/v2/object"
|
||||||
|
"github.com/TrueCloudLab/frostfs-api-go/v2/reputation"
|
||||||
|
"github.com/TrueCloudLab/frostfs-api-go/v2/session"
|
||||||
|
)
|
||||||
|
|
||||||
|
func serviceMessageBody(req interface{}) stableMarshaler {
|
||||||
|
switch v := req.(type) {
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("unsupported session message %T", req))
|
||||||
|
|
||||||
|
/* Accounting */
|
||||||
|
case *accounting.BalanceRequest:
|
||||||
|
return v.GetBody()
|
||||||
|
case *accounting.BalanceResponse:
|
||||||
|
return v.GetBody()
|
||||||
|
|
||||||
|
/* Session */
|
||||||
|
case *session.CreateRequest:
|
||||||
|
return v.GetBody()
|
||||||
|
case *session.CreateResponse:
|
||||||
|
return v.GetBody()
|
||||||
|
|
||||||
|
/* Container */
|
||||||
|
case *container.PutRequest:
|
||||||
|
return v.GetBody()
|
||||||
|
case *container.PutResponse:
|
||||||
|
return v.GetBody()
|
||||||
|
case *container.DeleteRequest:
|
||||||
|
return v.GetBody()
|
||||||
|
case *container.DeleteResponse:
|
||||||
|
return v.GetBody()
|
||||||
|
case *container.GetRequest:
|
||||||
|
return v.GetBody()
|
||||||
|
case *container.GetResponse:
|
||||||
|
return v.GetBody()
|
||||||
|
case *container.ListRequest:
|
||||||
|
return v.GetBody()
|
||||||
|
case *container.ListResponse:
|
||||||
|
return v.GetBody()
|
||||||
|
case *container.SetExtendedACLRequest:
|
||||||
|
return v.GetBody()
|
||||||
|
case *container.SetExtendedACLResponse:
|
||||||
|
return v.GetBody()
|
||||||
|
case *container.GetExtendedACLRequest:
|
||||||
|
return v.GetBody()
|
||||||
|
case *container.GetExtendedACLResponse:
|
||||||
|
return v.GetBody()
|
||||||
|
case *container.AnnounceUsedSpaceRequest:
|
||||||
|
return v.GetBody()
|
||||||
|
case *container.AnnounceUsedSpaceResponse:
|
||||||
|
return v.GetBody()
|
||||||
|
|
||||||
|
/* Object */
|
||||||
|
case *object.PutRequest:
|
||||||
|
return v.GetBody()
|
||||||
|
case *object.PutResponse:
|
||||||
|
return v.GetBody()
|
||||||
|
case *object.GetRequest:
|
||||||
|
return v.GetBody()
|
||||||
|
case *object.GetResponse:
|
||||||
|
return v.GetBody()
|
||||||
|
case *object.HeadRequest:
|
||||||
|
return v.GetBody()
|
||||||
|
case *object.HeadResponse:
|
||||||
|
return v.GetBody()
|
||||||
|
case *object.SearchRequest:
|
||||||
|
return v.GetBody()
|
||||||
|
case *object.SearchResponse:
|
||||||
|
return v.GetBody()
|
||||||
|
case *object.DeleteRequest:
|
||||||
|
return v.GetBody()
|
||||||
|
case *object.DeleteResponse:
|
||||||
|
return v.GetBody()
|
||||||
|
case *object.GetRangeRequest:
|
||||||
|
return v.GetBody()
|
||||||
|
case *object.GetRangeResponse:
|
||||||
|
return v.GetBody()
|
||||||
|
case *object.GetRangeHashRequest:
|
||||||
|
return v.GetBody()
|
||||||
|
case *object.GetRangeHashResponse:
|
||||||
|
return v.GetBody()
|
||||||
|
|
||||||
|
/* Netmap */
|
||||||
|
case *netmap.LocalNodeInfoRequest:
|
||||||
|
return v.GetBody()
|
||||||
|
case *netmap.LocalNodeInfoResponse:
|
||||||
|
return v.GetBody()
|
||||||
|
case *netmap.NetworkInfoRequest:
|
||||||
|
return v.GetBody()
|
||||||
|
case *netmap.NetworkInfoResponse:
|
||||||
|
return v.GetBody()
|
||||||
|
case *netmap.SnapshotRequest:
|
||||||
|
return v.GetBody()
|
||||||
|
case *netmap.SnapshotResponse:
|
||||||
|
return v.GetBody()
|
||||||
|
|
||||||
|
/* Reputation */
|
||||||
|
case *reputation.AnnounceLocalTrustRequest:
|
||||||
|
return v.GetBody()
|
||||||
|
case *reputation.AnnounceLocalTrustResponse:
|
||||||
|
return v.GetBody()
|
||||||
|
case *reputation.AnnounceIntermediateResultRequest:
|
||||||
|
return v.GetBody()
|
||||||
|
case *reputation.AnnounceIntermediateResultResponse:
|
||||||
|
return v.GetBody()
|
||||||
|
}
|
||||||
|
}
|
26
signature/marshaller.go
Normal file
26
signature/marshaller.go
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
package signature
|
||||||
|
|
||||||
|
type stableMarshaler interface {
|
||||||
|
StableMarshal([]byte) []byte
|
||||||
|
StableSize() int
|
||||||
|
}
|
||||||
|
|
||||||
|
type StableMarshalerWrapper struct {
|
||||||
|
SM stableMarshaler
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s StableMarshalerWrapper) ReadSignedData(buf []byte) ([]byte, error) {
|
||||||
|
if s.SM != nil {
|
||||||
|
return s.SM.StableMarshal(buf), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s StableMarshalerWrapper) SignedDataSize() int {
|
||||||
|
if s.SM != nil {
|
||||||
|
return s.SM.StableSize()
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
|
@ -2,17 +2,12 @@ package signature
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/TrueCloudLab/frostfs-api-go/v2/accounting"
|
|
||||||
"github.com/TrueCloudLab/frostfs-api-go/v2/container"
|
|
||||||
"github.com/TrueCloudLab/frostfs-api-go/v2/netmap"
|
|
||||||
"github.com/TrueCloudLab/frostfs-api-go/v2/object"
|
|
||||||
"github.com/TrueCloudLab/frostfs-api-go/v2/refs"
|
"github.com/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||||
"github.com/TrueCloudLab/frostfs-api-go/v2/reputation"
|
|
||||||
"github.com/TrueCloudLab/frostfs-api-go/v2/session"
|
"github.com/TrueCloudLab/frostfs-api-go/v2/session"
|
||||||
"github.com/TrueCloudLab/frostfs-api-go/v2/util/signature"
|
"github.com/TrueCloudLab/frostfs-api-go/v2/util/signature"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
)
|
)
|
||||||
|
|
||||||
type serviceRequest interface {
|
type serviceRequest interface {
|
||||||
|
@ -27,170 +22,80 @@ type serviceResponse interface {
|
||||||
SetVerificationHeader(*session.ResponseVerificationHeader)
|
SetVerificationHeader(*session.ResponseVerificationHeader)
|
||||||
}
|
}
|
||||||
|
|
||||||
type stableMarshaler interface {
|
type signatureReceiver interface {
|
||||||
StableMarshal([]byte) []byte
|
|
||||||
StableSize() int
|
|
||||||
}
|
|
||||||
|
|
||||||
type StableMarshalerWrapper struct {
|
|
||||||
SM stableMarshaler
|
|
||||||
}
|
|
||||||
|
|
||||||
type metaHeader interface {
|
|
||||||
stableMarshaler
|
|
||||||
getOrigin() metaHeader
|
|
||||||
}
|
|
||||||
|
|
||||||
type verificationHeader interface {
|
|
||||||
stableMarshaler
|
|
||||||
|
|
||||||
GetBodySignature() *refs.Signature
|
|
||||||
SetBodySignature(*refs.Signature)
|
SetBodySignature(*refs.Signature)
|
||||||
GetMetaSignature() *refs.Signature
|
|
||||||
SetMetaSignature(*refs.Signature)
|
SetMetaSignature(*refs.Signature)
|
||||||
GetOriginSignature() *refs.Signature
|
|
||||||
SetOriginSignature(*refs.Signature)
|
SetOriginSignature(*refs.Signature)
|
||||||
|
|
||||||
setOrigin(stableMarshaler)
|
|
||||||
getOrigin() verificationHeader
|
|
||||||
}
|
|
||||||
|
|
||||||
type requestMetaHeader struct {
|
|
||||||
*session.RequestMetaHeader
|
|
||||||
}
|
|
||||||
|
|
||||||
type responseMetaHeader struct {
|
|
||||||
*session.ResponseMetaHeader
|
|
||||||
}
|
|
||||||
|
|
||||||
type requestVerificationHeader struct {
|
|
||||||
*session.RequestVerificationHeader
|
|
||||||
}
|
|
||||||
|
|
||||||
type responseVerificationHeader struct {
|
|
||||||
*session.ResponseVerificationHeader
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *requestMetaHeader) getOrigin() metaHeader {
|
|
||||||
return &requestMetaHeader{
|
|
||||||
RequestMetaHeader: h.GetOrigin(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *responseMetaHeader) getOrigin() metaHeader {
|
|
||||||
return &responseMetaHeader{
|
|
||||||
ResponseMetaHeader: h.GetOrigin(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *requestVerificationHeader) getOrigin() verificationHeader {
|
|
||||||
if origin := h.GetOrigin(); origin != nil {
|
|
||||||
return &requestVerificationHeader{
|
|
||||||
RequestVerificationHeader: origin,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *requestVerificationHeader) setOrigin(m stableMarshaler) {
|
|
||||||
if m != nil {
|
|
||||||
h.SetOrigin(m.(*session.RequestVerificationHeader))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *responseVerificationHeader) getOrigin() verificationHeader {
|
|
||||||
if origin := r.GetOrigin(); origin != nil {
|
|
||||||
return &responseVerificationHeader{
|
|
||||||
ResponseVerificationHeader: origin,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *responseVerificationHeader) setOrigin(m stableMarshaler) {
|
|
||||||
if m != nil {
|
|
||||||
r.SetOrigin(m.(*session.ResponseVerificationHeader))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s StableMarshalerWrapper) ReadSignedData(buf []byte) ([]byte, error) {
|
|
||||||
if s.SM != nil {
|
|
||||||
return s.SM.StableMarshal(buf), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s StableMarshalerWrapper) SignedDataSize() int {
|
|
||||||
if s.SM != nil {
|
|
||||||
return s.SM.StableSize()
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SignServiceMessage signes service message with key.
|
||||||
func SignServiceMessage(key *ecdsa.PrivateKey, msg interface{}) error {
|
func SignServiceMessage(key *ecdsa.PrivateKey, msg interface{}) error {
|
||||||
var (
|
|
||||||
body, meta, verifyOrigin stableMarshaler
|
|
||||||
verifyHdr verificationHeader
|
|
||||||
verifyHdrSetter func(verificationHeader)
|
|
||||||
)
|
|
||||||
|
|
||||||
switch v := msg.(type) {
|
switch v := msg.(type) {
|
||||||
case nil:
|
case nil:
|
||||||
return nil
|
return nil
|
||||||
case serviceRequest:
|
case serviceRequest:
|
||||||
body = serviceMessageBody(v)
|
return signServiceRequest(key, v)
|
||||||
meta = v.GetMetaHeader()
|
|
||||||
verifyHdr = &requestVerificationHeader{new(session.RequestVerificationHeader)}
|
|
||||||
verifyHdrSetter = func(h verificationHeader) {
|
|
||||||
v.SetVerificationHeader(h.(*requestVerificationHeader).RequestVerificationHeader)
|
|
||||||
}
|
|
||||||
|
|
||||||
if h := v.GetVerificationHeader(); h != nil {
|
|
||||||
verifyOrigin = h
|
|
||||||
}
|
|
||||||
case serviceResponse:
|
case serviceResponse:
|
||||||
body = serviceMessageBody(v)
|
return signServiceResponse(key, v)
|
||||||
meta = v.GetMetaHeader()
|
|
||||||
verifyHdr = &responseVerificationHeader{new(session.ResponseVerificationHeader)}
|
|
||||||
verifyHdrSetter = func(h verificationHeader) {
|
|
||||||
v.SetVerificationHeader(h.(*responseVerificationHeader).ResponseVerificationHeader)
|
|
||||||
}
|
|
||||||
|
|
||||||
if h := v.GetVerificationHeader(); h != nil {
|
|
||||||
verifyOrigin = h
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("unsupported session message %T", v))
|
panic(fmt.Sprintf("unsupported session message %T", v))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if verifyOrigin == nil {
|
func signServiceRequest(key *ecdsa.PrivateKey, v serviceRequest) error {
|
||||||
|
result := &session.RequestVerificationHeader{}
|
||||||
|
body := serviceMessageBody(v)
|
||||||
|
meta := v.GetMetaHeader()
|
||||||
|
header := v.GetVerificationHeader()
|
||||||
|
if err := signMessageParts(key, body, meta, header, header != nil, result); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
result.SetOrigin(header)
|
||||||
|
v.SetVerificationHeader(result)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func signServiceResponse(key *ecdsa.PrivateKey, v serviceResponse) error {
|
||||||
|
result := &session.ResponseVerificationHeader{}
|
||||||
|
body := serviceMessageBody(v)
|
||||||
|
meta := v.GetMetaHeader()
|
||||||
|
header := v.GetVerificationHeader()
|
||||||
|
if err := signMessageParts(key, body, meta, header, header != nil, result); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
result.SetOrigin(header)
|
||||||
|
v.SetVerificationHeader(result)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func signMessageParts(key *ecdsa.PrivateKey, body, meta, header stableMarshaler, hasHeader bool, result signatureReceiver) error {
|
||||||
|
eg := &errgroup.Group{}
|
||||||
|
if !hasHeader {
|
||||||
// sign session message body
|
// sign session message body
|
||||||
if err := signServiceMessagePart(key, body, verifyHdr.SetBodySignature); err != nil {
|
eg.Go(func() error {
|
||||||
return fmt.Errorf("could not sign body: %w", err)
|
if err := signServiceMessagePart(key, body, result.SetBodySignature); err != nil {
|
||||||
}
|
return fmt.Errorf("could not sign body: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// sign meta header
|
// sign meta header
|
||||||
if err := signServiceMessagePart(key, meta, verifyHdr.SetMetaSignature); err != nil {
|
eg.Go(func() error {
|
||||||
return fmt.Errorf("could not sign meta header: %w", err)
|
if err := signServiceMessagePart(key, meta, result.SetMetaSignature); err != nil {
|
||||||
}
|
return fmt.Errorf("could not sign meta header: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
// sign verification header origin
|
// sign verification header origin
|
||||||
if err := signServiceMessagePart(key, verifyOrigin, verifyHdr.SetOriginSignature); err != nil {
|
eg.Go(func() error {
|
||||||
return fmt.Errorf("could not sign origin of verification header: %w", err)
|
if err := signServiceMessagePart(key, header, result.SetOriginSignature); err != nil {
|
||||||
}
|
return fmt.Errorf("could not sign origin of verification header: %w", err)
|
||||||
|
}
|
||||||
// wrap origin verification header
|
return nil
|
||||||
verifyHdr.setOrigin(verifyOrigin)
|
})
|
||||||
|
return eg.Wait()
|
||||||
// update matryoshka verification header
|
|
||||||
verifyHdrSetter(verifyHdr)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func signServiceMessagePart(key *ecdsa.PrivateKey, part stableMarshaler, sigWrite func(*refs.Signature)) error {
|
func signServiceMessagePart(key *ecdsa.PrivateKey, part stableMarshaler, sigWrite func(*refs.Signature)) error {
|
||||||
|
@ -212,182 +117,3 @@ func signServiceMessagePart(key *ecdsa.PrivateKey, part stableMarshaler, sigWrit
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func VerifyServiceMessage(msg interface{}) error {
|
|
||||||
var (
|
|
||||||
meta metaHeader
|
|
||||||
verify verificationHeader
|
|
||||||
)
|
|
||||||
|
|
||||||
switch v := msg.(type) {
|
|
||||||
case nil:
|
|
||||||
return nil
|
|
||||||
case serviceRequest:
|
|
||||||
meta = &requestMetaHeader{
|
|
||||||
RequestMetaHeader: v.GetMetaHeader(),
|
|
||||||
}
|
|
||||||
|
|
||||||
verify = &requestVerificationHeader{
|
|
||||||
RequestVerificationHeader: v.GetVerificationHeader(),
|
|
||||||
}
|
|
||||||
case serviceResponse:
|
|
||||||
meta = &responseMetaHeader{
|
|
||||||
ResponseMetaHeader: v.GetMetaHeader(),
|
|
||||||
}
|
|
||||||
|
|
||||||
verify = &responseVerificationHeader{
|
|
||||||
ResponseVerificationHeader: v.GetVerificationHeader(),
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
panic(fmt.Sprintf("unsupported session message %T", v))
|
|
||||||
}
|
|
||||||
|
|
||||||
body := serviceMessageBody(msg)
|
|
||||||
size := body.StableSize()
|
|
||||||
if sz := meta.StableSize(); sz > size {
|
|
||||||
size = sz
|
|
||||||
}
|
|
||||||
if sz := verify.StableSize(); sz > size {
|
|
||||||
size = sz
|
|
||||||
}
|
|
||||||
|
|
||||||
buf := make([]byte, 0, size)
|
|
||||||
return verifyMatryoshkaLevel(body, meta, verify, buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
func verifyMatryoshkaLevel(body stableMarshaler, meta metaHeader, verify verificationHeader, buf []byte) error {
|
|
||||||
if err := verifyServiceMessagePart(meta, verify.GetMetaSignature, buf); err != nil {
|
|
||||||
return fmt.Errorf("could not verify meta header: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
origin := verify.getOrigin()
|
|
||||||
|
|
||||||
if err := verifyServiceMessagePart(origin, verify.GetOriginSignature, buf); err != nil {
|
|
||||||
return fmt.Errorf("could not verify origin of verification header: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if origin == nil {
|
|
||||||
if err := verifyServiceMessagePart(body, verify.GetBodySignature, buf); err != nil {
|
|
||||||
return fmt.Errorf("could not verify body: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if verify.GetBodySignature() != nil {
|
|
||||||
return errors.New("body signature at the matryoshka upper level")
|
|
||||||
}
|
|
||||||
|
|
||||||
return verifyMatryoshkaLevel(body, meta.getOrigin(), origin, buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
func verifyServiceMessagePart(part stableMarshaler, sigRdr func() *refs.Signature, buf []byte) error {
|
|
||||||
return signature.VerifyDataWithSource(
|
|
||||||
&StableMarshalerWrapper{part},
|
|
||||||
sigRdr,
|
|
||||||
signature.WithBuffer(buf),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func serviceMessageBody(req interface{}) stableMarshaler {
|
|
||||||
switch v := req.(type) {
|
|
||||||
default:
|
|
||||||
panic(fmt.Sprintf("unsupported session message %T", req))
|
|
||||||
|
|
||||||
/* Accounting */
|
|
||||||
case *accounting.BalanceRequest:
|
|
||||||
return v.GetBody()
|
|
||||||
case *accounting.BalanceResponse:
|
|
||||||
return v.GetBody()
|
|
||||||
|
|
||||||
/* Session */
|
|
||||||
case *session.CreateRequest:
|
|
||||||
return v.GetBody()
|
|
||||||
case *session.CreateResponse:
|
|
||||||
return v.GetBody()
|
|
||||||
|
|
||||||
/* Container */
|
|
||||||
case *container.PutRequest:
|
|
||||||
return v.GetBody()
|
|
||||||
case *container.PutResponse:
|
|
||||||
return v.GetBody()
|
|
||||||
case *container.DeleteRequest:
|
|
||||||
return v.GetBody()
|
|
||||||
case *container.DeleteResponse:
|
|
||||||
return v.GetBody()
|
|
||||||
case *container.GetRequest:
|
|
||||||
return v.GetBody()
|
|
||||||
case *container.GetResponse:
|
|
||||||
return v.GetBody()
|
|
||||||
case *container.ListRequest:
|
|
||||||
return v.GetBody()
|
|
||||||
case *container.ListResponse:
|
|
||||||
return v.GetBody()
|
|
||||||
case *container.SetExtendedACLRequest:
|
|
||||||
return v.GetBody()
|
|
||||||
case *container.SetExtendedACLResponse:
|
|
||||||
return v.GetBody()
|
|
||||||
case *container.GetExtendedACLRequest:
|
|
||||||
return v.GetBody()
|
|
||||||
case *container.GetExtendedACLResponse:
|
|
||||||
return v.GetBody()
|
|
||||||
case *container.AnnounceUsedSpaceRequest:
|
|
||||||
return v.GetBody()
|
|
||||||
case *container.AnnounceUsedSpaceResponse:
|
|
||||||
return v.GetBody()
|
|
||||||
|
|
||||||
/* Object */
|
|
||||||
case *object.PutRequest:
|
|
||||||
return v.GetBody()
|
|
||||||
case *object.PutResponse:
|
|
||||||
return v.GetBody()
|
|
||||||
case *object.GetRequest:
|
|
||||||
return v.GetBody()
|
|
||||||
case *object.GetResponse:
|
|
||||||
return v.GetBody()
|
|
||||||
case *object.HeadRequest:
|
|
||||||
return v.GetBody()
|
|
||||||
case *object.HeadResponse:
|
|
||||||
return v.GetBody()
|
|
||||||
case *object.SearchRequest:
|
|
||||||
return v.GetBody()
|
|
||||||
case *object.SearchResponse:
|
|
||||||
return v.GetBody()
|
|
||||||
case *object.DeleteRequest:
|
|
||||||
return v.GetBody()
|
|
||||||
case *object.DeleteResponse:
|
|
||||||
return v.GetBody()
|
|
||||||
case *object.GetRangeRequest:
|
|
||||||
return v.GetBody()
|
|
||||||
case *object.GetRangeResponse:
|
|
||||||
return v.GetBody()
|
|
||||||
case *object.GetRangeHashRequest:
|
|
||||||
return v.GetBody()
|
|
||||||
case *object.GetRangeHashResponse:
|
|
||||||
return v.GetBody()
|
|
||||||
|
|
||||||
/* Netmap */
|
|
||||||
case *netmap.LocalNodeInfoRequest:
|
|
||||||
return v.GetBody()
|
|
||||||
case *netmap.LocalNodeInfoResponse:
|
|
||||||
return v.GetBody()
|
|
||||||
case *netmap.NetworkInfoRequest:
|
|
||||||
return v.GetBody()
|
|
||||||
case *netmap.NetworkInfoResponse:
|
|
||||||
return v.GetBody()
|
|
||||||
case *netmap.SnapshotRequest:
|
|
||||||
return v.GetBody()
|
|
||||||
case *netmap.SnapshotResponse:
|
|
||||||
return v.GetBody()
|
|
||||||
|
|
||||||
/* Reputation */
|
|
||||||
case *reputation.AnnounceLocalTrustRequest:
|
|
||||||
return v.GetBody()
|
|
||||||
case *reputation.AnnounceLocalTrustResponse:
|
|
||||||
return v.GetBody()
|
|
||||||
case *reputation.AnnounceIntermediateResultRequest:
|
|
||||||
return v.GetBody()
|
|
||||||
case *reputation.AnnounceIntermediateResultResponse:
|
|
||||||
return v.GetBody()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -70,3 +70,56 @@ func TestBalanceResponse(t *testing.T) {
|
||||||
// verification must fail
|
// verification must fail
|
||||||
require.Error(t, VerifyServiceMessage(req))
|
require.Error(t, VerifyServiceMessage(req))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BenchmarkSignRequest(b *testing.B) {
|
||||||
|
key, _ := crypto.LoadPrivateKey("Kwk6k2eC3L3QuPvD8aiaNyoSXgQ2YL1bwS5CP1oKoA9waeAze97s")
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
b.ReportAllocs()
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
b.StopTimer()
|
||||||
|
dec := new(accounting.Decimal)
|
||||||
|
dec.SetValue(100)
|
||||||
|
|
||||||
|
body := new(accounting.BalanceResponseBody)
|
||||||
|
body.SetBalance(dec)
|
||||||
|
|
||||||
|
meta := new(session.ResponseMetaHeader)
|
||||||
|
meta.SetTTL(1)
|
||||||
|
|
||||||
|
resp := new(accounting.BalanceResponse)
|
||||||
|
resp.SetBody(body)
|
||||||
|
resp.SetMetaHeader(meta)
|
||||||
|
|
||||||
|
b.StartTimer()
|
||||||
|
SignServiceMessage(key, resp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkVerifyRequest(b *testing.B) {
|
||||||
|
key, _ := crypto.LoadPrivateKey("Kwk6k2eC3L3QuPvD8aiaNyoSXgQ2YL1bwS5CP1oKoA9waeAze97s")
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
b.ReportAllocs()
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
b.StopTimer()
|
||||||
|
dec := new(accounting.Decimal)
|
||||||
|
dec.SetValue(100)
|
||||||
|
|
||||||
|
body := new(accounting.BalanceResponseBody)
|
||||||
|
body.SetBalance(dec)
|
||||||
|
|
||||||
|
meta := new(session.ResponseMetaHeader)
|
||||||
|
meta.SetTTL(1)
|
||||||
|
|
||||||
|
resp := new(accounting.BalanceResponse)
|
||||||
|
resp.SetBody(body)
|
||||||
|
resp.SetMetaHeader(meta)
|
||||||
|
SignServiceMessage(key, resp)
|
||||||
|
b.StartTimer()
|
||||||
|
|
||||||
|
VerifyServiceMessage(resp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
140
signature/verify.go
Normal file
140
signature/verify.go
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
package signature
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||||
|
"github.com/TrueCloudLab/frostfs-api-go/v2/session"
|
||||||
|
"github.com/TrueCloudLab/frostfs-api-go/v2/util/signature"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
|
)
|
||||||
|
|
||||||
|
type signatureProvider interface {
|
||||||
|
GetBodySignature() *refs.Signature
|
||||||
|
GetMetaSignature() *refs.Signature
|
||||||
|
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) {
|
||||||
|
case nil:
|
||||||
|
return nil
|
||||||
|
case serviceRequest:
|
||||||
|
return verifyServiceRequest(v)
|
||||||
|
case serviceResponse:
|
||||||
|
return verifyServiceResponse(v)
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("unsupported session message %T", v))
|
||||||
fixed fixed
fixed fixed
|
|||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func verifyServiceRequest(v serviceRequest) error {
|
||||||
|
meta := v.GetMetaHeader()
|
||||||
|
verificationHeader := v.GetVerificationHeader()
|
||||||
|
body := serviceMessageBody(v)
|
||||||
|
buffers := createBuffers(body.StableSize(), meta.StableSize(), verificationHeader.StableSize())
|
||||||
|
return verifyServiceRequestRecursive(body, meta, verificationHeader, buffers)
|
||||||
|
}
|
||||||
|
|
||||||
|
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, buffers)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if stop {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return verifyServiceRequestRecursive(body, metaOrigin, verificationHeaderOrigin, buffers)
|
||||||
|
}
|
||||||
|
|
||||||
|
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 := eg.Wait(); err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !hasOriginHeader {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if sigProvider.GetBodySignature() != nil {
|
||||||
|
return false, errors.New("body signature misses at the matryoshka upper level")
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func verifyServiceResponse(v serviceResponse) error {
|
||||||
|
meta := v.GetMetaHeader()
|
||||||
|
verificationHeader := v.GetVerificationHeader()
|
||||||
|
body := serviceMessageBody(v)
|
||||||
|
buffers := createBuffers(body.StableSize(), meta.StableSize(), verificationHeader.StableSize())
|
||||||
|
return verifyServiceResponseRecursive(body, meta, verificationHeader, buffers)
|
||||||
|
}
|
||||||
|
|
||||||
|
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, buffers)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if stop {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return verifyServiceResponseRecursive(body, metaOrigin, verificationHeaderOrigin, buffers)
|
||||||
|
}
|
||||||
|
|
||||||
|
func verifyServiceMessagePart(part stableMarshaler, sigRdr func() *refs.Signature, buf []byte) error {
|
||||||
|
return signature.VerifyDataWithSource(
|
||||||
|
&StableMarshalerWrapper{part},
|
||||||
|
sigRdr,
|
||||||
|
signature.WithBuffer(buf),
|
||||||
|
)
|
||||||
|
}
|
Loading…
Reference in a new issue
I am wondering if it makes sense to allocate once and use sub-slices here. Probably not, can bite us in an unexpected way.
Max
was here when we had a single buffer, do we need a singlesize
now?