forked from TrueCloudLab/frostfs-api-go
Implement new request signing mechanism
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
parent
59858805a8
commit
6191903326
9 changed files with 904 additions and 64 deletions
0
pkg/.gitkeep
Normal file
0
pkg/.gitkeep
Normal file
|
@ -1,64 +0,0 @@
|
||||||
package signature
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/ecdsa"
|
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
type SignedRequest interface {
|
|
||||||
RequestBody() DataSource
|
|
||||||
RequestMetaHeader() DataSource
|
|
||||||
OriginVerificationHeader() DataSource
|
|
||||||
|
|
||||||
SetBodySignatureWithKey(key, sig []byte)
|
|
||||||
BodySignatureWithKey() (key, sig []byte)
|
|
||||||
|
|
||||||
SetMetaSignatureWithKey(key, sig []byte)
|
|
||||||
MetaSignatureWithKey() (key, sig []byte)
|
|
||||||
|
|
||||||
SetOriginSignatureWithKey(key, sig []byte)
|
|
||||||
OriginSignatureWithKey() (key, sig []byte)
|
|
||||||
}
|
|
||||||
|
|
||||||
func SignRequest(key *ecdsa.PrivateKey, src SignedRequest) error {
|
|
||||||
if src == nil {
|
|
||||||
return errors.New("nil source")
|
|
||||||
}
|
|
||||||
|
|
||||||
// sign body
|
|
||||||
if err := SignDataWithHandler(key, src.RequestBody(), src.SetBodySignatureWithKey); err != nil {
|
|
||||||
return errors.Wrap(err, "could not sign body")
|
|
||||||
}
|
|
||||||
|
|
||||||
// sign meta
|
|
||||||
if err := SignDataWithHandler(key, src.RequestMetaHeader(), src.SetMetaSignatureWithKey); err != nil {
|
|
||||||
return errors.Wrap(err, "could not sign meta header")
|
|
||||||
}
|
|
||||||
|
|
||||||
// sign verify origin
|
|
||||||
if err := SignDataWithHandler(key, src.OriginVerificationHeader(), src.SetOriginSignatureWithKey); err != nil {
|
|
||||||
return errors.Wrap(err, "could not sign verification header origin")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func VerifyRequest(src SignedRequest) error {
|
|
||||||
// verify body signature
|
|
||||||
if err := VerifyDataWithSource(src.RequestBody(), src.BodySignatureWithKey); err != nil {
|
|
||||||
return errors.Wrap(err, "could not verify body")
|
|
||||||
}
|
|
||||||
|
|
||||||
// verify meta header
|
|
||||||
if err := VerifyDataWithSource(src.RequestMetaHeader(), src.MetaSignatureWithKey); err != nil {
|
|
||||||
return errors.Wrap(err, "could not verify meta header")
|
|
||||||
}
|
|
||||||
|
|
||||||
// verify verification header origin
|
|
||||||
if err := VerifyDataWithSource(src.OriginVerificationHeader(), src.OriginSignatureWithKey); err != nil {
|
|
||||||
return errors.Wrap(err, "could not verify verification header origin")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
85
v2/accounting.go
Normal file
85
v2/accounting.go
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
package v2
|
||||||
|
|
||||||
|
type BalanceRequestBody struct {
|
||||||
|
ownerID *OwnerID
|
||||||
|
}
|
||||||
|
|
||||||
|
type BalanceRequest struct {
|
||||||
|
body *BalanceRequestBody
|
||||||
|
|
||||||
|
metaHeader *RequestMetaHeader
|
||||||
|
|
||||||
|
verifyHeader *RequestVerificationHeader
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BalanceRequestBody) GetOwnerID() *OwnerID {
|
||||||
|
if b != nil {
|
||||||
|
return b.ownerID
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BalanceRequestBody) SetOwnerID(v *OwnerID) {
|
||||||
|
if b != nil {
|
||||||
|
b.ownerID = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *BalanceRequestBody) StableMarshal(buf []byte) ([]byte, error) {
|
||||||
|
if r == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: do not use hack
|
||||||
|
_, err := BalanceRequestBodyToGRPCMessage(r).MarshalTo(buf)
|
||||||
|
|
||||||
|
return buf, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *BalanceRequestBody) StableSize() int {
|
||||||
|
// TODO: do not use hack
|
||||||
|
return BalanceRequestBodyToGRPCMessage(r).Size()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BalanceRequest) GetBody() *BalanceRequestBody {
|
||||||
|
if b != nil {
|
||||||
|
return b.body
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BalanceRequest) SetBody(v *BalanceRequestBody) {
|
||||||
|
if b != nil {
|
||||||
|
b.body = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BalanceRequest) GetRequestMetaHeader() *RequestMetaHeader {
|
||||||
|
if b != nil {
|
||||||
|
return b.metaHeader
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BalanceRequest) SetRequestMetaHeader(v *RequestMetaHeader) {
|
||||||
|
if b != nil {
|
||||||
|
b.metaHeader = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BalanceRequest) GetRequestVerificationHeader() *RequestVerificationHeader {
|
||||||
|
if b != nil {
|
||||||
|
return b.verifyHeader
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BalanceRequest) SetRequestVerificationHeader(v *RequestVerificationHeader) {
|
||||||
|
if b != nil {
|
||||||
|
b.verifyHeader = v
|
||||||
|
}
|
||||||
|
}
|
351
v2/convert.go
Normal file
351
v2/convert.go
Normal file
|
@ -0,0 +1,351 @@
|
||||||
|
package v2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/nspcc-dev/neofs-api-go/v2/accounting"
|
||||||
|
"github.com/nspcc-dev/neofs-api-go/v2/refs"
|
||||||
|
"github.com/nspcc-dev/neofs-api-go/v2/service"
|
||||||
|
)
|
||||||
|
|
||||||
|
func SignatureToGRPCMessage(s *Signature) *service.Signature {
|
||||||
|
if s == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
m := new(service.Signature)
|
||||||
|
|
||||||
|
m.SetKey(s.GetKey())
|
||||||
|
m.SetSign(s.GetSign())
|
||||||
|
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func SignatureFromGRPCMessage(m *service.Signature) *Signature {
|
||||||
|
if m == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
s := new(Signature)
|
||||||
|
|
||||||
|
s.SetKey(m.GetKey())
|
||||||
|
s.SetSign(m.GetSign())
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func VersionToGRPCMessage(v *Version) *service.Version {
|
||||||
|
if v == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := new(service.Version)
|
||||||
|
|
||||||
|
msg.SetMajor(v.GetMajor())
|
||||||
|
msg.SetMinor(v.GetMinor())
|
||||||
|
|
||||||
|
return msg
|
||||||
|
}
|
||||||
|
|
||||||
|
func VersionFromGRPCMessage(m *service.Version) *Version {
|
||||||
|
if m == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
v := new(Version)
|
||||||
|
|
||||||
|
v.SetMajor(m.GetMajor())
|
||||||
|
v.SetMinor(m.GetMinor())
|
||||||
|
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
func XHeaderToGRPCMessage(x *XHeader) *service.XHeader {
|
||||||
|
if x == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
m := new(service.XHeader)
|
||||||
|
|
||||||
|
m.SetKey(x.GetKey())
|
||||||
|
m.SetValue(x.GetValue())
|
||||||
|
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func XHeaderFromGRPCMessage(m *service.XHeader) *XHeader {
|
||||||
|
if m == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
x := new(XHeader)
|
||||||
|
|
||||||
|
x.SetKey(m.GetKey())
|
||||||
|
x.SetValue(m.GetValue())
|
||||||
|
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
func SessionTokenToGRPCMessage(t *SessionToken) *service.SessionToken {
|
||||||
|
// TODO: fill me
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func SessionTokenFromGRPCMessage(m *service.SessionToken) *SessionToken {
|
||||||
|
// TODO: fill me
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func BearerTokenToGRPCMessage(t *BearerToken) *service.BearerToken {
|
||||||
|
// TODO: fill me
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func BearerTokenFromGRPCMessage(m *service.BearerToken) *BearerToken {
|
||||||
|
// TODO: fill me
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func RequestVerificationHeaderToGRPCMessage(r *RequestVerificationHeader) *service.RequestVerificationHeader {
|
||||||
|
if r == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
m := new(service.RequestVerificationHeader)
|
||||||
|
|
||||||
|
m.SetBodySignature(
|
||||||
|
SignatureToGRPCMessage(r.GetBodySignature()),
|
||||||
|
)
|
||||||
|
|
||||||
|
m.SetMetaSignature(
|
||||||
|
SignatureToGRPCMessage(r.GetMetaSignature()),
|
||||||
|
)
|
||||||
|
|
||||||
|
m.SetOriginSignature(
|
||||||
|
SignatureToGRPCMessage(r.GetOriginSignature()),
|
||||||
|
)
|
||||||
|
|
||||||
|
m.SetOrigin(
|
||||||
|
RequestVerificationHeaderToGRPCMessage(r.GetOrigin()),
|
||||||
|
)
|
||||||
|
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func RequestVerificationHeaderFromGRPCMessage(m *service.RequestVerificationHeader) *RequestVerificationHeader {
|
||||||
|
if m == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
r := new(RequestVerificationHeader)
|
||||||
|
|
||||||
|
r.SetBodySignature(
|
||||||
|
SignatureFromGRPCMessage(m.GetBodySignature()),
|
||||||
|
)
|
||||||
|
|
||||||
|
r.SetMetaSignature(
|
||||||
|
SignatureFromGRPCMessage(m.GetMetaSignature()),
|
||||||
|
)
|
||||||
|
|
||||||
|
r.SetOriginSignature(
|
||||||
|
SignatureFromGRPCMessage(m.GetOriginSignature()),
|
||||||
|
)
|
||||||
|
|
||||||
|
r.SetOrigin(
|
||||||
|
RequestVerificationHeaderFromGRPCMessage(m.GetOrigin()),
|
||||||
|
)
|
||||||
|
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func RequestMetaHeaderToGRPCMessage(r *RequestMetaHeader) *service.RequestMetaHeader {
|
||||||
|
if r == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
m := new(service.RequestMetaHeader)
|
||||||
|
|
||||||
|
m.SetTtl(r.GetTTL())
|
||||||
|
m.SetEpoch(r.GetEpoch())
|
||||||
|
|
||||||
|
m.SetVersion(
|
||||||
|
VersionToGRPCMessage(r.GetVersion()),
|
||||||
|
)
|
||||||
|
|
||||||
|
m.SetSessionToken(
|
||||||
|
SessionTokenToGRPCMessage(r.GetSessionToken()),
|
||||||
|
)
|
||||||
|
|
||||||
|
m.SetBearerToken(
|
||||||
|
BearerTokenToGRPCMessage(r.GetBearerToken()),
|
||||||
|
)
|
||||||
|
|
||||||
|
m.SetOrigin(
|
||||||
|
RequestMetaHeaderToGRPCMessage(r.GetOrigin()),
|
||||||
|
)
|
||||||
|
|
||||||
|
xHeaders := r.GetXHeaders()
|
||||||
|
xHdrMsg := make([]*service.XHeader, 0, len(xHeaders))
|
||||||
|
|
||||||
|
for i := range xHeaders {
|
||||||
|
xHdrMsg = append(xHdrMsg, XHeaderToGRPCMessage(xHeaders[i]))
|
||||||
|
}
|
||||||
|
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func RequestMetaHeaderFromGRPCMessage(m *service.RequestMetaHeader) *RequestMetaHeader {
|
||||||
|
if m == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
r := new(RequestMetaHeader)
|
||||||
|
|
||||||
|
r.SetTTL(m.GetTtl())
|
||||||
|
r.SetEpoch(m.GetEpoch())
|
||||||
|
|
||||||
|
r.SetVersion(
|
||||||
|
VersionFromGRPCMessage(m.GetVersion()),
|
||||||
|
)
|
||||||
|
|
||||||
|
r.SetSessionToken(
|
||||||
|
SessionTokenFromGRPCMessage(m.GetSessionToken()),
|
||||||
|
)
|
||||||
|
|
||||||
|
r.SetBearerToken(
|
||||||
|
BearerTokenFromGRPCMessage(m.GetBearerToken()),
|
||||||
|
)
|
||||||
|
|
||||||
|
r.SetOrigin(
|
||||||
|
RequestMetaHeaderFromGRPCMessage(m.GetOrigin()),
|
||||||
|
)
|
||||||
|
|
||||||
|
xHdrMsg := m.GetXHeaders()
|
||||||
|
xHeaders := make([]*XHeader, 0, len(xHdrMsg))
|
||||||
|
|
||||||
|
for i := range xHdrMsg {
|
||||||
|
xHeaders = append(xHeaders, XHeaderFromGRPCMessage(xHdrMsg[i]))
|
||||||
|
}
|
||||||
|
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func OwnerIDToGRPCMessage(o *OwnerID) *refs.OwnerID {
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
m := new(refs.OwnerID)
|
||||||
|
|
||||||
|
m.SetValue(o.GetValue())
|
||||||
|
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func OwnerIDFromGRPCMessage(m *refs.OwnerID) *OwnerID {
|
||||||
|
if m == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
o := new(OwnerID)
|
||||||
|
|
||||||
|
o.SetValue(m.GetValue())
|
||||||
|
|
||||||
|
return o
|
||||||
|
}
|
||||||
|
|
||||||
|
func BalanceRequestBodyToGRPCMessage(b *BalanceRequestBody) *accounting.BalanceRequest_Body {
|
||||||
|
if b == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
m := new(accounting.BalanceRequest_Body)
|
||||||
|
|
||||||
|
m.SetOwnerId(
|
||||||
|
OwnerIDToGRPCMessage(b.GetOwnerID()),
|
||||||
|
)
|
||||||
|
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func BalanceRequestBodyFromGRPCMessage(m *accounting.BalanceRequest_Body) *BalanceRequestBody {
|
||||||
|
if m == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
b := new(BalanceRequestBody)
|
||||||
|
|
||||||
|
b.SetOwnerID(
|
||||||
|
OwnerIDFromGRPCMessage(m.GetOwnerId()),
|
||||||
|
)
|
||||||
|
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
func headersToGRPC(
|
||||||
|
src interface {
|
||||||
|
GetRequestMetaHeader() *RequestMetaHeader
|
||||||
|
GetRequestVerificationHeader() *RequestVerificationHeader
|
||||||
|
},
|
||||||
|
dst interface {
|
||||||
|
SetMetaHeader(*service.RequestMetaHeader)
|
||||||
|
SetVerifyHeader(*service.RequestVerificationHeader)
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
dst.SetMetaHeader(
|
||||||
|
RequestMetaHeaderToGRPCMessage(src.GetRequestMetaHeader()),
|
||||||
|
)
|
||||||
|
|
||||||
|
dst.SetVerifyHeader(
|
||||||
|
RequestVerificationHeaderToGRPCMessage(src.GetRequestVerificationHeader()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func headersFromGRPC(
|
||||||
|
src interface {
|
||||||
|
GetMetaHeader() *service.RequestMetaHeader
|
||||||
|
GetVerifyHeader() *service.RequestVerificationHeader
|
||||||
|
},
|
||||||
|
dst interface {
|
||||||
|
SetRequestMetaHeader(*RequestMetaHeader)
|
||||||
|
SetRequestVerificationHeader(*RequestVerificationHeader)
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
dst.SetRequestMetaHeader(
|
||||||
|
RequestMetaHeaderFromGRPCMessage(src.GetMetaHeader()),
|
||||||
|
)
|
||||||
|
|
||||||
|
dst.SetRequestVerificationHeader(
|
||||||
|
RequestVerificationHeaderFromGRPCMessage(src.GetVerifyHeader()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BalanceRequestToGRPCMessage(b *BalanceRequest) *accounting.BalanceRequest {
|
||||||
|
if b == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
m := new(accounting.BalanceRequest)
|
||||||
|
|
||||||
|
m.SetBody(
|
||||||
|
BalanceRequestBodyToGRPCMessage(b.GetBody()),
|
||||||
|
)
|
||||||
|
|
||||||
|
headersToGRPC(b, m)
|
||||||
|
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func BalanceRequestFromGRPCMessage(m *accounting.BalanceRequest) *BalanceRequest {
|
||||||
|
if m == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
b := new(BalanceRequest)
|
||||||
|
|
||||||
|
b.SetBody(
|
||||||
|
BalanceRequestBodyFromGRPCMessage(m.GetBody()),
|
||||||
|
)
|
||||||
|
|
||||||
|
headersFromGRPC(m, b)
|
||||||
|
|
||||||
|
return b
|
||||||
|
}
|
331
v2/service.go
Normal file
331
v2/service.go
Normal file
|
@ -0,0 +1,331 @@
|
||||||
|
package v2
|
||||||
|
|
||||||
|
type Signature struct {
|
||||||
|
key, sign []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type Version struct {
|
||||||
|
major, minor uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type XHeader struct {
|
||||||
|
key, val string
|
||||||
|
}
|
||||||
|
|
||||||
|
type SessionToken struct {
|
||||||
|
// TODO: fill me
|
||||||
|
}
|
||||||
|
|
||||||
|
type BearerToken struct {
|
||||||
|
// TODO: fill me
|
||||||
|
}
|
||||||
|
|
||||||
|
type RequestVerificationHeader struct {
|
||||||
|
bodySig, metaSig, originSig *Signature
|
||||||
|
|
||||||
|
origin *RequestVerificationHeader
|
||||||
|
}
|
||||||
|
|
||||||
|
type RequestMetaHeader struct {
|
||||||
|
version *Version
|
||||||
|
|
||||||
|
ttl uint32
|
||||||
|
|
||||||
|
epoch uint64
|
||||||
|
|
||||||
|
xHeaders []*XHeader
|
||||||
|
|
||||||
|
sessionToken *SessionToken
|
||||||
|
|
||||||
|
bearerToken *BearerToken
|
||||||
|
|
||||||
|
origin *RequestMetaHeader
|
||||||
|
}
|
||||||
|
|
||||||
|
type OwnerID struct {
|
||||||
|
val []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Signature) GetKey() []byte {
|
||||||
|
if s != nil {
|
||||||
|
return s.key
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Signature) SetKey(v []byte) {
|
||||||
|
if s != nil {
|
||||||
|
s.key = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Signature) GetSign() []byte {
|
||||||
|
if s != nil {
|
||||||
|
return s.sign
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Signature) SetSign(v []byte) {
|
||||||
|
if s != nil {
|
||||||
|
s.sign = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Version) GetMajor() uint32 {
|
||||||
|
if v != nil {
|
||||||
|
return v.major
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Version) SetMajor(val uint32) {
|
||||||
|
if v != nil {
|
||||||
|
v.major = val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Version) GetMinor() uint32 {
|
||||||
|
if v != nil {
|
||||||
|
return v.minor
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Version) SetMinor(val uint32) {
|
||||||
|
if v != nil {
|
||||||
|
v.minor = val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *XHeader) GetKey() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.key
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *XHeader) SetKey(v string) {
|
||||||
|
if x != nil {
|
||||||
|
x.key = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *XHeader) GetValue() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.val
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *XHeader) SetValue(v string) {
|
||||||
|
if x != nil {
|
||||||
|
x.val = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RequestVerificationHeader) GetBodySignature() *Signature {
|
||||||
|
if r != nil {
|
||||||
|
return r.bodySig
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RequestVerificationHeader) SetBodySignature(v *Signature) {
|
||||||
|
if r != nil {
|
||||||
|
r.bodySig = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RequestVerificationHeader) GetMetaSignature() *Signature {
|
||||||
|
if r != nil {
|
||||||
|
return r.metaSig
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RequestVerificationHeader) SetMetaSignature(v *Signature) {
|
||||||
|
if r != nil {
|
||||||
|
r.metaSig = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RequestVerificationHeader) GetOriginSignature() *Signature {
|
||||||
|
if r != nil {
|
||||||
|
return r.originSig
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RequestVerificationHeader) SetOriginSignature(v *Signature) {
|
||||||
|
if r != nil {
|
||||||
|
r.originSig = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RequestVerificationHeader) GetOrigin() *RequestVerificationHeader {
|
||||||
|
if r != nil {
|
||||||
|
return r.origin
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RequestVerificationHeader) SetOrigin(v *RequestVerificationHeader) {
|
||||||
|
if r != nil {
|
||||||
|
r.origin = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RequestVerificationHeader) StableMarshal(buf []byte) ([]byte, error) {
|
||||||
|
if r == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: do not use hack
|
||||||
|
_, err := RequestVerificationHeaderToGRPCMessage(r).MarshalTo(buf)
|
||||||
|
|
||||||
|
return buf, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RequestVerificationHeader) StableSize() int {
|
||||||
|
// TODO: do not use hack
|
||||||
|
return RequestVerificationHeaderToGRPCMessage(r).Size()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RequestMetaHeader) GetVersion() *Version {
|
||||||
|
if r != nil {
|
||||||
|
return r.version
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RequestMetaHeader) SetVersion(v *Version) {
|
||||||
|
if r != nil {
|
||||||
|
r.version = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RequestMetaHeader) GetTTL() uint32 {
|
||||||
|
if r != nil {
|
||||||
|
return r.ttl
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RequestMetaHeader) SetTTL(v uint32) {
|
||||||
|
if r != nil {
|
||||||
|
r.ttl = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RequestMetaHeader) GetEpoch() uint64 {
|
||||||
|
if r != nil {
|
||||||
|
return r.epoch
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RequestMetaHeader) SetEpoch(v uint64) {
|
||||||
|
if r != nil {
|
||||||
|
r.epoch = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RequestMetaHeader) GetXHeaders() []*XHeader {
|
||||||
|
if r != nil {
|
||||||
|
return r.xHeaders
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RequestMetaHeader) SetXHeaders(v []*XHeader) {
|
||||||
|
if r != nil {
|
||||||
|
r.xHeaders = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RequestMetaHeader) GetSessionToken() *SessionToken {
|
||||||
|
if r != nil {
|
||||||
|
return r.sessionToken
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RequestMetaHeader) SetSessionToken(v *SessionToken) {
|
||||||
|
if r != nil {
|
||||||
|
r.sessionToken = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RequestMetaHeader) GetBearerToken() *BearerToken {
|
||||||
|
if r != nil {
|
||||||
|
return r.bearerToken
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RequestMetaHeader) SetBearerToken(v *BearerToken) {
|
||||||
|
if r != nil {
|
||||||
|
r.bearerToken = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RequestMetaHeader) GetOrigin() *RequestMetaHeader {
|
||||||
|
if r != nil {
|
||||||
|
return r.origin
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RequestMetaHeader) SetOrigin(v *RequestMetaHeader) {
|
||||||
|
if r != nil {
|
||||||
|
r.origin = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RequestMetaHeader) StableMarshal(buf []byte) ([]byte, error) {
|
||||||
|
if r == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: do not use hack
|
||||||
|
_, err := RequestMetaHeaderToGRPCMessage(r).MarshalTo(buf)
|
||||||
|
|
||||||
|
return buf, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RequestMetaHeader) StableSize() int {
|
||||||
|
// TODO: do not use hack
|
||||||
|
return RequestMetaHeaderToGRPCMessage(r).Size()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *OwnerID) GetValue() []byte {
|
||||||
|
if o != nil {
|
||||||
|
return o.val
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *OwnerID) SetValue(v []byte) {
|
||||||
|
if o != nil {
|
||||||
|
o.val = v
|
||||||
|
}
|
||||||
|
}
|
137
v2/signature/sign.go
Normal file
137
v2/signature/sign.go
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
package signature
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/ecdsa"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neofs-api-go/util/signature"
|
||||||
|
v2 "github.com/nspcc-dev/neofs-api-go/v2"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SignedRequest interface {
|
||||||
|
GetRequestMetaHeader() *v2.RequestMetaHeader
|
||||||
|
GetRequestVerificationHeader() *v2.RequestVerificationHeader
|
||||||
|
SetRequestVerificationHeader(*v2.RequestVerificationHeader)
|
||||||
|
}
|
||||||
|
|
||||||
|
type stableMarshaler interface {
|
||||||
|
StableMarshal([]byte) ([]byte, error)
|
||||||
|
StableSize() int
|
||||||
|
}
|
||||||
|
|
||||||
|
type stableMarshalerWrapper struct {
|
||||||
|
sm stableMarshaler
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s stableMarshalerWrapper) ReadSignedData(buf []byte) ([]byte, error) {
|
||||||
|
return s.sm.StableMarshal(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s stableMarshalerWrapper) SignedDataSize() int {
|
||||||
|
return s.sm.StableSize()
|
||||||
|
}
|
||||||
|
|
||||||
|
func keySignatureHandler(s *v2.Signature) signature.KeySignatureHandler {
|
||||||
|
return func(key []byte, sig []byte) {
|
||||||
|
s.SetKey(key)
|
||||||
|
s.SetSign(sig)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func keySignatureSource(s *v2.Signature) signature.KeySignatureSource {
|
||||||
|
return func() ([]byte, []byte) {
|
||||||
|
return s.GetKey(), s.GetSign()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func requestBody(req SignedRequest) stableMarshaler {
|
||||||
|
switch v := req.(type) {
|
||||||
|
case *v2.BalanceRequest:
|
||||||
|
return v.GetBody()
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("unknown request %T", req))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func SignRequest(key *ecdsa.PrivateKey, req SignedRequest) error {
|
||||||
|
if req == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// create new level of matryoshka
|
||||||
|
verifyHdr := new(v2.RequestVerificationHeader)
|
||||||
|
|
||||||
|
// attach the previous matryoshka
|
||||||
|
verifyHdr.SetOrigin(req.GetRequestVerificationHeader())
|
||||||
|
|
||||||
|
// sign request body
|
||||||
|
if err := signRequestPart(key, requestBody(req), verifyHdr.SetBodySignature); err != nil {
|
||||||
|
return errors.Wrap(err, "could not sign request body")
|
||||||
|
}
|
||||||
|
|
||||||
|
// sign meta header
|
||||||
|
if err := signRequestPart(key, req.GetRequestMetaHeader(), verifyHdr.SetMetaSignature); err != nil {
|
||||||
|
return errors.Wrap(err, "could not sign request meta header")
|
||||||
|
}
|
||||||
|
|
||||||
|
// sign verification header origin
|
||||||
|
if err := signRequestPart(key, verifyHdr.GetOrigin(), verifyHdr.SetOriginSignature); err != nil {
|
||||||
|
return errors.Wrap(err, "could not sign origin of request verification header")
|
||||||
|
}
|
||||||
|
|
||||||
|
// make a new top of the matryoshka
|
||||||
|
req.SetRequestVerificationHeader(verifyHdr)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func signRequestPart(key *ecdsa.PrivateKey, part stableMarshaler, sigWrite func(*v2.Signature)) error {
|
||||||
|
sig := new(v2.Signature)
|
||||||
|
|
||||||
|
// sign part
|
||||||
|
if err := signature.SignDataWithHandler(
|
||||||
|
key,
|
||||||
|
&stableMarshalerWrapper{part},
|
||||||
|
keySignatureHandler(sig),
|
||||||
|
); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// write part signature
|
||||||
|
sigWrite(sig)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func VerifyRequest(req SignedRequest) error {
|
||||||
|
verifyHdr := req.GetRequestVerificationHeader()
|
||||||
|
|
||||||
|
// verify body signature
|
||||||
|
if err := verifyRequestPart(requestBody(req), verifyHdr.GetBodySignature); err != nil {
|
||||||
|
return errors.Wrap(err, "could not verify request body")
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify meta header
|
||||||
|
if err := verifyRequestPart(req.GetRequestMetaHeader(), verifyHdr.GetMetaSignature); err != nil {
|
||||||
|
return errors.Wrap(err, "could not verify request meta header")
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify verification header origin
|
||||||
|
if err := verifyRequestPart(verifyHdr.GetOrigin(), verifyHdr.GetOriginSignature); err != nil {
|
||||||
|
return errors.Wrap(err, "could not verify origin of request verification header")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func verifyRequestPart(part stableMarshaler, sigRdr func() *v2.Signature) error {
|
||||||
|
if err := signature.VerifyDataWithSource(
|
||||||
|
&stableMarshalerWrapper{part},
|
||||||
|
keySignatureSource(sigRdr()),
|
||||||
|
); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Reference in a new issue