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