forked from TrueCloudLab/frostfs-api-go
Merge pull request #67 from nspcc-dev/update-to-neofs-api-0.7.2
Update to neofs api 0.7.2
This commit is contained in:
commit
6c705e079f
29 changed files with 192 additions and 459 deletions
2
Makefile
2
Makefile
|
@ -1,4 +1,4 @@
|
|||
PROTO_VERSION=v0.7.1
|
||||
PROTO_VERSION=v0.7.2
|
||||
PROTO_URL=https://github.com/nspcc-dev/neofs-api/archive/$(PROTO_VERSION).tar.gz
|
||||
|
||||
B=\033[0;1m
|
||||
|
|
|
@ -149,7 +149,6 @@ calculated for XORed data.
|
|||
| ----- | ---- | ----- | ----------- |
|
||||
| Address | [refs.Address](#refs.Address) | | Address of object (container id + object id) |
|
||||
| OwnerID | [bytes](#bytes) | | OwnerID is a wallet address |
|
||||
| Token | [session.Token](#session.Token) | | Token with session public key and user's signature |
|
||||
| Meta | [service.RequestMetaHeader](#service.RequestMetaHeader) | | RequestMetaHeader contains information about request meta headers (should be embedded into message) |
|
||||
| Verify | [service.RequestVerificationHeader](#service.RequestVerificationHeader) | | RequestVerificationHeader is a set of signatures of every NeoFS Node that processed request (should be embedded into message) |
|
||||
|
||||
|
@ -228,7 +227,6 @@ in distributed system.
|
|||
| Field | Type | Label | Description |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| Address | [refs.Address](#refs.Address) | | Address of object (container id + object id) |
|
||||
| Raw | [bool](#bool) | | Raw is the request flag of a physically stored representation of an object |
|
||||
| Meta | [service.RequestMetaHeader](#service.RequestMetaHeader) | | RequestMetaHeader contains information about request meta headers (should be embedded into message) |
|
||||
| Verify | [service.RequestVerificationHeader](#service.RequestVerificationHeader) | | RequestVerificationHeader is a set of signatures of every NeoFS Node that processed request (should be embedded into message) |
|
||||
|
||||
|
@ -256,7 +254,6 @@ in distributed system.
|
|||
| ----- | ---- | ----- | ----------- |
|
||||
| Address | [refs.Address](#refs.Address) | | Address of object (container id + object id) |
|
||||
| FullHeaders | [bool](#bool) | | FullHeaders can be set true for extended headers in the object |
|
||||
| Raw | [bool](#bool) | | Raw is the request flag of a physically stored representation of an object |
|
||||
| Meta | [service.RequestMetaHeader](#service.RequestMetaHeader) | | RequestMetaHeader contains information about request meta headers (should be embedded into message) |
|
||||
| Verify | [service.RequestVerificationHeader](#service.RequestVerificationHeader) | | RequestVerificationHeader is a set of signatures of every NeoFS Node that processed request (should be embedded into message) |
|
||||
|
||||
|
@ -296,7 +293,6 @@ in distributed system.
|
|||
| Field | Type | Label | Description |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| Object | [Object](#object.Object) | | Object with at least container id and owner id fields |
|
||||
| Token | [session.Token](#session.Token) | | Token with session public key and user's signature |
|
||||
| CopiesNumber | [uint32](#uint32) | | Number of the object copies to store within the RPC call (zero is processed according to the placement rules) |
|
||||
|
||||
|
||||
|
@ -378,7 +374,7 @@ in distributed system.
|
|||
| UserHeader | [UserHeader](#object.UserHeader) | | UserHeader is a set of KV headers defined by user |
|
||||
| Transform | [Transform](#object.Transform) | | Transform defines transform operation (e.g. payload split) |
|
||||
| Tombstone | [Tombstone](#object.Tombstone) | | Tombstone header that set up in deleted objects |
|
||||
| Verify | [session.VerificationHeader](#session.VerificationHeader) | | Verify header that contains session public key and user's signature |
|
||||
| Token | [service.Token](#service.Token) | | Token header contains token of the session within which the object was created |
|
||||
| HomoHash | [bytes](#bytes) | | HomoHash is a homomorphic hash of original object payload |
|
||||
| PayloadChecksum | [bytes](#bytes) | | PayloadChecksum of actual object's payload |
|
||||
| Integrity | [IntegrityHeader](#object.IntegrityHeader) | | Integrity header with checksum of all above headers in the object |
|
||||
|
|
|
@ -14,8 +14,9 @@
|
|||
|
||||
- Messages
|
||||
- [RequestVerificationHeader](#service.RequestVerificationHeader)
|
||||
- [RequestVerificationHeader.Sign](#service.RequestVerificationHeader.Sign)
|
||||
- [RequestVerificationHeader.Signature](#service.RequestVerificationHeader.Signature)
|
||||
- [Token](#service.Token)
|
||||
- [Token.Info](#service.Token.Info)
|
||||
|
||||
|
||||
- [service/verify_test.proto](#service/verify_test.proto)
|
||||
|
@ -49,6 +50,7 @@ RequestMetaHeader contains information about request meta headers
|
|||
| TTL | [uint32](#uint32) | | TTL must be larger than zero, it decreased in every NeoFS Node |
|
||||
| Epoch | [uint64](#uint64) | | Epoch for user can be empty, because node sets epoch to the actual value |
|
||||
| Version | [uint32](#uint32) | | Version defines protocol version TODO: not used for now, should be implemented in future |
|
||||
| Raw | [bool](#bool) | | Raw determines whether the request is raw or not |
|
||||
|
||||
|
||||
<a name="service.ResponseMetaHeader"></a>
|
||||
|
@ -88,18 +90,7 @@ RequestVerificationHeader is a set of signatures of every NeoFS Node that proces
|
|||
| Field | Type | Label | Description |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| Signatures | [RequestVerificationHeader.Signature](#service.RequestVerificationHeader.Signature) | repeated | Signatures is a set of signatures of every passed NeoFS Node |
|
||||
|
||||
|
||||
<a name="service.RequestVerificationHeader.Sign"></a>
|
||||
|
||||
### Message RequestVerificationHeader.Sign
|
||||
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| Sign | [bytes](#bytes) | | Sign is signature of the request or session key. |
|
||||
| Peer | [bytes](#bytes) | | Peer is compressed public key used for signature. |
|
||||
| Token | [Token](#service.Token) | | Token is a token of the session within which the request is sent |
|
||||
|
||||
|
||||
<a name="service.RequestVerificationHeader.Signature"></a>
|
||||
|
@ -110,11 +101,57 @@ RequestVerificationHeader is a set of signatures of every NeoFS Node that proces
|
|||
|
||||
| Field | Type | Label | Description |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| Sign | [RequestVerificationHeader.Sign](#service.RequestVerificationHeader.Sign) | | Sign is a signature and public key of the request. |
|
||||
| Origin | [RequestVerificationHeader.Sign](#service.RequestVerificationHeader.Sign) | | Origin used for requests, when trusted node changes it and re-sign with session key. If session key used for signature request, then Origin should contain public key of user and signed session key. |
|
||||
| Sign | [bytes](#bytes) | | Sign is signature of the request or session key. |
|
||||
| Peer | [bytes](#bytes) | | Peer is compressed public key used for signature. |
|
||||
|
||||
|
||||
<a name="service.Token"></a>
|
||||
|
||||
### Message Token
|
||||
User token granting rights for object manipulation
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| TokenInfo | [Token.Info](#service.Token.Info) | | TokenInfo is a grouped information about token |
|
||||
| Signature | [bytes](#bytes) | | Signature is a signature of session token information |
|
||||
|
||||
|
||||
<a name="service.Token.Info"></a>
|
||||
|
||||
### Message Token.Info
|
||||
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| ID | [bytes](#bytes) | | ID is a token identifier. valid UUIDv4 represented in bytes |
|
||||
| OwnerID | [bytes](#bytes) | | OwnerID is an owner of manipulation object |
|
||||
| verb | [Token.Info.Verb](#service.Token.Info.Verb) | | Verb is a type of request for which the token is issued |
|
||||
| Address | [refs.Address](#refs.Address) | | Address is an object address for which token is issued |
|
||||
| Created | [uint64](#uint64) | | Created is an initial epoch of token lifetime |
|
||||
| ValidUntil | [uint64](#uint64) | | ValidUntil is a last epoch of token lifetime |
|
||||
| SessionKey | [bytes](#bytes) | | SessionKey is a public key of session key |
|
||||
|
||||
<!-- end messages -->
|
||||
|
||||
|
||||
<a name="service.Token.Info.Verb"></a>
|
||||
|
||||
### Token.Info.Verb
|
||||
Verb is an enumeration of session request types
|
||||
|
||||
| Name | Number | Description |
|
||||
| ---- | ------ | ----------- |
|
||||
| Put | 0 | Put refers to object.Put RPC call |
|
||||
| Get | 1 | Get refers to object.Get RPC call |
|
||||
| Head | 2 | Head refers to object.Head RPC call |
|
||||
| Search | 3 | Search refers to object.Search RPC call |
|
||||
| Delete | 4 | Delete refers to object.Delete RPC call |
|
||||
| Range | 5 | Range refers to object.GetRange RPC call |
|
||||
| RangeHash | 6 | RangeHash refers to object.GetRangeHash RPC call |
|
||||
|
||||
|
||||
<!-- end enums -->
|
||||
|
||||
|
||||
|
|
|
@ -12,13 +12,6 @@
|
|||
- [CreateResponse](#session.CreateResponse)
|
||||
|
||||
|
||||
- [session/types.proto](#session/types.proto)
|
||||
|
||||
- Messages
|
||||
- [Token](#session.Token)
|
||||
- [VerificationHeader](#session.VerificationHeader)
|
||||
|
||||
|
||||
- [Scalar Value Types](#scalar-value-types)
|
||||
|
||||
|
||||
|
@ -68,8 +61,8 @@ session key. Session is established during 4-step handshake in one gRPC stream
|
|||
|
||||
| Field | Type | Label | Description |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| Init | [Token](#session.Token) | | Init is a message to initialize session opening. Carry: owner of manipulation object; ID of manipulation object; token lifetime bounds. |
|
||||
| Signed | [Token](#session.Token) | | Signed Init message response (Unsigned) from server with user private key |
|
||||
| Init | [service.Token](#service.Token) | | Init is a message to initialize session opening. Carry: owner of manipulation object; ID of manipulation object; token lifetime bounds. |
|
||||
| Signed | [service.Token](#service.Token) | | Signed Init message response (Unsigned) from server with user private key |
|
||||
| Meta | [service.RequestMetaHeader](#service.RequestMetaHeader) | | RequestMetaHeader contains information about request meta headers (should be embedded into message) |
|
||||
| Verify | [service.RequestVerificationHeader](#service.RequestVerificationHeader) | | RequestVerificationHeader is a set of signatures of every NeoFS Node that processed request (should be embedded into message) |
|
||||
|
||||
|
@ -82,52 +75,8 @@ session key. Session is established during 4-step handshake in one gRPC stream
|
|||
|
||||
| Field | Type | Label | Description |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| Unsigned | [Token](#session.Token) | | Unsigned token with token ID and session public key generated on server side |
|
||||
| Result | [Token](#session.Token) | | Result is a resulting token which can be used for object placing through an trusted intermediary |
|
||||
|
||||
<!-- end messages -->
|
||||
|
||||
<!-- end enums -->
|
||||
|
||||
|
||||
|
||||
<a name="session/types.proto"></a>
|
||||
<p align="right"><a href="#top">Top</a></p>
|
||||
|
||||
## session/types.proto
|
||||
|
||||
|
||||
<!-- end services -->
|
||||
|
||||
|
||||
<a name="session.Token"></a>
|
||||
|
||||
### Message Token
|
||||
User token granting rights for object manipulation
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| Header | [VerificationHeader](#session.VerificationHeader) | | Header carries verification data of session key |
|
||||
| OwnerID | [bytes](#bytes) | | OwnerID is an owner of manipulation object |
|
||||
| FirstEpoch | [uint64](#uint64) | | FirstEpoch is an initial epoch of token lifetime |
|
||||
| LastEpoch | [uint64](#uint64) | | LastEpoch is a last epoch of token lifetime |
|
||||
| ObjectID | [bytes](#bytes) | repeated | ObjectID is an object identifier of manipulation object |
|
||||
| Signature | [bytes](#bytes) | | Signature is a token signature, signed by owner of manipulation object |
|
||||
| ID | [bytes](#bytes) | | ID is a token identifier. valid UUIDv4 represented in bytes |
|
||||
| PublicKeys | [bytes](#bytes) | repeated | PublicKeys associated with owner |
|
||||
|
||||
|
||||
<a name="session.VerificationHeader"></a>
|
||||
|
||||
### Message VerificationHeader
|
||||
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| PublicKey | [bytes](#bytes) | | PublicKey is a session public key |
|
||||
| KeySignature | [bytes](#bytes) | | KeySignature is a session public key signature. Signed by trusted side |
|
||||
| Unsigned | [service.Token](#service.Token) | | Unsigned token with token ID and session public key generated on server side |
|
||||
| Result | [service.Token](#service.Token) | | Result is a resulting token which can be used for object placing through an trusted intermediary |
|
||||
|
||||
<!-- end messages -->
|
||||
|
||||
|
|
|
@ -19,21 +19,6 @@ func (m Object) IsLinking() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// VerificationHeader returns verification header if it is presented in extended headers.
|
||||
func (m Object) VerificationHeader() (*VerificationHeader, error) {
|
||||
_, vh := m.LastHeader(HeaderType(VerifyHdr))
|
||||
if vh == nil {
|
||||
return nil, ErrHeaderNotFound
|
||||
}
|
||||
return vh.Value.(*Header_Verify).Verify, nil
|
||||
}
|
||||
|
||||
// SetVerificationHeader sets verification header in the object.
|
||||
// It will replace existing verification header or add a new one.
|
||||
func (m *Object) SetVerificationHeader(header *VerificationHeader) {
|
||||
m.SetHeader(&Header{Value: &Header_Verify{Verify: header}})
|
||||
}
|
||||
|
||||
// Links returns slice of ids of specified link type
|
||||
func (m *Object) Links(t Link_Type) []ID {
|
||||
var res []ID
|
||||
|
|
Binary file not shown.
|
@ -5,7 +5,6 @@ option csharp_namespace = "NeoFS.API.Object";
|
|||
|
||||
import "refs/types.proto";
|
||||
import "object/types.proto";
|
||||
import "session/types.proto";
|
||||
import "service/meta.proto";
|
||||
import "service/verify.proto";
|
||||
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
|
||||
|
@ -58,8 +57,6 @@ service Service {
|
|||
message GetRequest {
|
||||
// Address of object (container id + object id)
|
||||
refs.Address Address = 1 [(gogoproto.nullable) = false];
|
||||
// Raw is the request flag of a physically stored representation of an object
|
||||
bool Raw = 2;
|
||||
// RequestMetaHeader contains information about request meta headers (should be embedded into message)
|
||||
service.RequestMetaHeader Meta = 98 [(gogoproto.embed) = true, (gogoproto.nullable) = false];
|
||||
// RequestVerificationHeader is a set of signatures of every NeoFS Node that processed request (should be embedded into message)
|
||||
|
@ -82,10 +79,8 @@ message PutRequest {
|
|||
message PutHeader {
|
||||
// Object with at least container id and owner id fields
|
||||
Object Object = 1;
|
||||
// Token with session public key and user's signature
|
||||
session.Token Token = 2;
|
||||
// Number of the object copies to store within the RPC call (zero is processed according to the placement rules)
|
||||
uint32 CopiesNumber = 3;
|
||||
uint32 CopiesNumber = 2;
|
||||
}
|
||||
|
||||
oneof R {
|
||||
|
@ -112,8 +107,6 @@ message DeleteRequest {
|
|||
refs.Address Address = 1 [(gogoproto.nullable) = false];
|
||||
// OwnerID is a wallet address
|
||||
bytes OwnerID = 2 [(gogoproto.nullable) = false, (gogoproto.customtype) = "OwnerID"];
|
||||
// Token with session public key and user's signature
|
||||
session.Token Token = 3;
|
||||
// RequestMetaHeader contains information about request meta headers (should be embedded into message)
|
||||
service.RequestMetaHeader Meta = 98 [(gogoproto.embed) = true, (gogoproto.nullable) = false];
|
||||
// RequestVerificationHeader is a set of signatures of every NeoFS Node that processed request (should be embedded into message)
|
||||
|
@ -132,8 +125,6 @@ message HeadRequest {
|
|||
refs.Address Address = 1 [(gogoproto.nullable) = false, (gogoproto.customtype) = "Address"];
|
||||
// FullHeaders can be set true for extended headers in the object
|
||||
bool FullHeaders = 2;
|
||||
// Raw is the request flag of a physically stored representation of an object
|
||||
bool Raw = 3;
|
||||
// RequestMetaHeader contains information about request meta headers (should be embedded into message)
|
||||
service.RequestMetaHeader Meta = 98 [(gogoproto.embed) = true, (gogoproto.nullable) = false];
|
||||
// RequestVerificationHeader is a set of signatures of every NeoFS Node that processed request (should be embedded into message)
|
||||
|
|
|
@ -16,8 +16,8 @@ func TestRequest(t *testing.T) {
|
|||
&DeleteRequest{},
|
||||
&GetRangeRequest{},
|
||||
&GetRangeHashRequest{},
|
||||
MakePutRequestHeader(nil, nil),
|
||||
MakePutRequestHeader(&Object{}, nil),
|
||||
MakePutRequestHeader(nil),
|
||||
MakePutRequestHeader(&Object{}),
|
||||
}
|
||||
|
||||
types := []RequestType{
|
||||
|
|
|
@ -7,7 +7,6 @@ import (
|
|||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/nspcc-dev/neofs-api-go/internal"
|
||||
"github.com/nspcc-dev/neofs-api-go/refs"
|
||||
"github.com/nspcc-dev/neofs-api-go/session"
|
||||
)
|
||||
|
||||
type (
|
||||
|
@ -19,9 +18,6 @@ type (
|
|||
// Address is a type alias of object Address.
|
||||
Address = refs.Address
|
||||
|
||||
// VerificationHeader is a type alias of session's verification header.
|
||||
VerificationHeader = session.VerificationHeader
|
||||
|
||||
// PositionReader defines object reader that returns slice of bytes
|
||||
// for specified object and data range.
|
||||
PositionReader interface {
|
||||
|
@ -60,8 +56,8 @@ const (
|
|||
TransformHdr
|
||||
// TombstoneHdr is a tombstone header type.
|
||||
TombstoneHdr
|
||||
// VerifyHdr is a verification header type.
|
||||
VerifyHdr
|
||||
// TokenHdr is a token header type.
|
||||
TokenHdr
|
||||
// HomoHashHdr is a homomorphic hash header type.
|
||||
HomoHashHdr
|
||||
// PayloadChecksumHdr is a payload checksum header type.
|
||||
|
@ -175,8 +171,8 @@ func (m Header) typeOf(t isHeader_Value) (ok bool) {
|
|||
_, ok = m.Value.(*Header_Transform)
|
||||
case *Header_Tombstone:
|
||||
_, ok = m.Value.(*Header_Tombstone)
|
||||
case *Header_Verify:
|
||||
_, ok = m.Value.(*Header_Verify)
|
||||
case *Header_Token:
|
||||
_, ok = m.Value.(*Header_Token)
|
||||
case *Header_HomoHash:
|
||||
_, ok = m.Value.(*Header_HomoHash)
|
||||
case *Header_PayloadChecksum:
|
||||
|
@ -205,8 +201,8 @@ func HeaderType(t headerType) Pred {
|
|||
return func(h *Header) bool { _, ok := h.Value.(*Header_Transform); return ok }
|
||||
case TombstoneHdr:
|
||||
return func(h *Header) bool { _, ok := h.Value.(*Header_Tombstone); return ok }
|
||||
case VerifyHdr:
|
||||
return func(h *Header) bool { _, ok := h.Value.(*Header_Verify); return ok }
|
||||
case TokenHdr:
|
||||
return func(h *Header) bool { _, ok := h.Value.(*Header_Token); return ok }
|
||||
case HomoHashHdr:
|
||||
return func(h *Header) bool { _, ok := h.Value.(*Header_HomoHash); return ok }
|
||||
case PayloadChecksumHdr:
|
||||
|
|
Binary file not shown.
|
@ -4,7 +4,7 @@ option go_package = "github.com/nspcc-dev/neofs-api-go/object";
|
|||
option csharp_namespace = "NeoFS.API.Object";
|
||||
|
||||
import "refs/types.proto";
|
||||
import "session/types.proto";
|
||||
import "service/verify.proto";
|
||||
import "storagegroup/types.proto";
|
||||
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
|
||||
|
||||
|
@ -36,8 +36,8 @@ message Header {
|
|||
Transform Transform = 4;
|
||||
// Tombstone header that set up in deleted objects
|
||||
Tombstone Tombstone = 5;
|
||||
// Verify header that contains session public key and user's signature
|
||||
session.VerificationHeader Verify = 6;
|
||||
// Token header contains token of the session within which the object was created
|
||||
service.Token Token = 6;
|
||||
// HomoHash is a homomorphic hash of original object payload
|
||||
bytes HomoHash = 7 [(gogoproto.customtype) = "Hash"];
|
||||
// PayloadChecksum of actual object's payload
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"io"
|
||||
"strconv"
|
||||
|
||||
"github.com/nspcc-dev/neofs-api-go/session"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
|
@ -46,11 +45,10 @@ func (b ByteSize) String() string {
|
|||
|
||||
// MakePutRequestHeader combines object and session token value
|
||||
// into header of object put request.
|
||||
func MakePutRequestHeader(obj *Object, token *session.Token) *PutRequest {
|
||||
func MakePutRequestHeader(obj *Object) *PutRequest {
|
||||
return &PutRequest{
|
||||
R: &PutRequest_Header{Header: &PutRequest_PutHeader{
|
||||
Object: obj,
|
||||
Token: token,
|
||||
}},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ func (m Object) Verify() error {
|
|||
integrity := ih.Value.(*Header_Integrity).Integrity
|
||||
|
||||
// Prepare structures
|
||||
_, vh := m.LastHeader(HeaderType(VerifyHdr))
|
||||
_, vh := m.LastHeader(HeaderType(TokenHdr))
|
||||
if vh == nil {
|
||||
_, pkh := m.LastHeader(HeaderType(PublicKeyHdr))
|
||||
if pkh == nil {
|
||||
|
@ -85,7 +85,7 @@ func (m Object) Verify() error {
|
|||
}
|
||||
pubkey = pkh.Value.(*Header_PublicKey).PublicKey.Value
|
||||
} else {
|
||||
pubkey = vh.Value.(*Header_Verify).Verify.PublicKey
|
||||
pubkey = vh.Value.(*Header_Token).Token.SessionKey
|
||||
}
|
||||
|
||||
// Verify signature
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
"github.com/google/uuid"
|
||||
"github.com/nspcc-dev/neofs-api-go/container"
|
||||
"github.com/nspcc-dev/neofs-api-go/refs"
|
||||
"github.com/nspcc-dev/neofs-api-go/session"
|
||||
"github.com/nspcc-dev/neofs-api-go/service"
|
||||
crypto "github.com/nspcc-dev/neofs-crypto"
|
||||
"github.com/nspcc-dev/neofs-crypto/test"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
@ -77,11 +77,13 @@ func TestObject_Verify(t *testing.T) {
|
|||
|
||||
dataPK := crypto.MarshalPublicKey(&sessionkey.PublicKey)
|
||||
signature, err = crypto.Sign(key, dataPK)
|
||||
vh := &session.VerificationHeader{
|
||||
PublicKey: dataPK,
|
||||
KeySignature: signature,
|
||||
tok := &service.Token{
|
||||
Token_Info: service.Token_Info{
|
||||
SessionKey: dataPK,
|
||||
},
|
||||
Signature: signature,
|
||||
}
|
||||
obj.SetVerificationHeader(vh)
|
||||
obj.AddHeader(&Header{Value: &Header_Token{Token: tok}})
|
||||
|
||||
// validation header is not last
|
||||
t.Run("error validation header is not last", func(t *testing.T) {
|
||||
|
@ -90,7 +92,7 @@ func TestObject_Verify(t *testing.T) {
|
|||
})
|
||||
|
||||
obj.Headers = obj.Headers[:len(obj.Headers)-2]
|
||||
obj.SetVerificationHeader(vh)
|
||||
obj.AddHeader(&Header{Value: &Header_Token{Token: tok}})
|
||||
obj.SetHeader(&Header{Value: &Header_Integrity{ih}})
|
||||
|
||||
t.Run("error invalid header checksum", func(t *testing.T) {
|
||||
|
@ -115,7 +117,7 @@ func TestObject_Verify(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
obj.SetHeader(genIH)
|
||||
|
||||
t.Run("correct with vh", func(t *testing.T) {
|
||||
t.Run("correct with tok", func(t *testing.T) {
|
||||
err = obj.Verify()
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
@ -123,7 +125,7 @@ func TestObject_Verify(t *testing.T) {
|
|||
pkh := Header{Value: &Header_PublicKey{&PublicKey{
|
||||
Value: crypto.MarshalPublicKey(&key.PublicKey),
|
||||
}}}
|
||||
// replace vh with pkh
|
||||
// replace tok with pkh
|
||||
obj.Headers[len(obj.Headers)-2] = pkh
|
||||
// re-sign object
|
||||
obj.Sign(sessionkey)
|
||||
|
|
14
service/alias.go
Normal file
14
service/alias.go
Normal file
|
@ -0,0 +1,14 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"github.com/nspcc-dev/neofs-api-go/refs"
|
||||
)
|
||||
|
||||
// TokenID is type alias of UUID ref.
|
||||
type TokenID = refs.UUID
|
||||
|
||||
// OwnerID is type alias of OwnerID ref.
|
||||
type OwnerID = refs.OwnerID
|
||||
|
||||
// Address is type alias of Address ref.
|
||||
type Address = refs.Address
|
Binary file not shown.
|
@ -17,6 +17,8 @@ message RequestMetaHeader {
|
|||
// Version defines protocol version
|
||||
// TODO: not used for now, should be implemented in future
|
||||
uint32 Version = 3;
|
||||
// Raw determines whether the request is raw or not
|
||||
bool Raw = 4;
|
||||
}
|
||||
|
||||
// ResponseMetaHeader contains meta information based on request processing by server
|
||||
|
|
|
@ -53,18 +53,6 @@ func (m *RequestVerificationHeader) AddSignature(sig *RequestVerificationHeader_
|
|||
m.Signatures = append(m.Signatures, sig)
|
||||
}
|
||||
|
||||
// SetOwner adds origin (sign and public key) of owner (client) into first signature.
|
||||
func (m *RequestVerificationHeader) SetOwner(pub *ecdsa.PublicKey, sign []byte) {
|
||||
if len(m.Signatures) == 0 || pub == nil {
|
||||
return
|
||||
}
|
||||
|
||||
m.Signatures[0].Origin = &RequestVerificationHeader_Sign{
|
||||
Sign: sign,
|
||||
Peer: crypto.MarshalPublicKey(pub),
|
||||
}
|
||||
}
|
||||
|
||||
// CheckOwner validates, that passed OwnerID is equal to present PublicKey of owner.
|
||||
func (m *RequestVerificationHeader) CheckOwner(owner refs.OwnerID) error {
|
||||
if key, err := m.GetOwner(); err != nil {
|
||||
|
@ -83,18 +71,6 @@ func (m *RequestVerificationHeader) CheckOwner(owner refs.OwnerID) error {
|
|||
func (m *RequestVerificationHeader) GetOwner() (*ecdsa.PublicKey, error) {
|
||||
if len(m.Signatures) == 0 {
|
||||
return nil, ErrCannotFindOwner
|
||||
}
|
||||
|
||||
// if first signature contains origin, we should try to validate session key
|
||||
if m.Signatures[0].Origin != nil {
|
||||
owner := crypto.UnmarshalPublicKey(m.Signatures[0].Origin.Peer)
|
||||
if owner == nil {
|
||||
return nil, ErrCannotLoadPublicKey
|
||||
} else if err := crypto.Verify(owner, m.Signatures[0].Peer, m.Signatures[0].Origin.Sign); err != nil {
|
||||
return nil, errors.Wrap(err, "could not verify session token")
|
||||
}
|
||||
|
||||
return owner, nil
|
||||
} else if key := crypto.UnmarshalPublicKey(m.Signatures[0].Peer); key != nil {
|
||||
return key, nil
|
||||
}
|
||||
|
@ -128,10 +104,8 @@ func newSignature(key *ecdsa.PrivateKey, data []byte) (*RequestVerificationHeade
|
|||
}
|
||||
|
||||
return &RequestVerificationHeader_Signature{
|
||||
RequestVerificationHeader_Sign: RequestVerificationHeader_Sign{
|
||||
Sign: sign,
|
||||
Peer: crypto.MarshalPublicKey(&key.PublicKey),
|
||||
},
|
||||
Sign: sign,
|
||||
Peer: crypto.MarshalPublicKey(&key.PublicKey),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
Binary file not shown.
|
@ -3,6 +3,7 @@ package service;
|
|||
option go_package = "github.com/nspcc-dev/neofs-api-go/service";
|
||||
option csharp_namespace = "NeoFS.API.Service";
|
||||
|
||||
import "refs/types.proto";
|
||||
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
|
||||
|
||||
option (gogoproto.stable_marshaler_all) = true;
|
||||
|
@ -10,22 +11,74 @@ option (gogoproto.stable_marshaler_all) = true;
|
|||
// RequestVerificationHeader is a set of signatures of every NeoFS Node that processed request
|
||||
// (should be embedded into message).
|
||||
message RequestVerificationHeader {
|
||||
message Sign {
|
||||
message Signature {
|
||||
// Sign is signature of the request or session key.
|
||||
bytes Sign = 1;
|
||||
// Peer is compressed public key used for signature.
|
||||
bytes Peer = 2;
|
||||
}
|
||||
|
||||
message Signature {
|
||||
// Sign is a signature and public key of the request.
|
||||
Sign Sign = 1 [(gogoproto.embed) = true, (gogoproto.nullable) = false];
|
||||
// Origin used for requests, when trusted node changes it and re-sign with session key.
|
||||
// If session key used for signature request, then Origin should contain
|
||||
// public key of user and signed session key.
|
||||
Sign Origin = 2;
|
||||
}
|
||||
|
||||
// Signatures is a set of signatures of every passed NeoFS Node
|
||||
repeated Signature Signatures = 1;
|
||||
|
||||
// Token is a token of the session within which the request is sent
|
||||
Token Token = 2;
|
||||
}
|
||||
|
||||
// User token granting rights for object manipulation
|
||||
message Token {
|
||||
message Info {
|
||||
// ID is a token identifier. valid UUIDv4 represented in bytes
|
||||
bytes ID = 1 [(gogoproto.customtype) = "TokenID", (gogoproto.nullable) = false];
|
||||
|
||||
// OwnerID is an owner of manipulation object
|
||||
bytes OwnerID = 2 [(gogoproto.customtype) = "OwnerID", (gogoproto.nullable) = false];
|
||||
|
||||
// Verb is an enumeration of session request types
|
||||
enum Verb {
|
||||
// Put refers to object.Put RPC call
|
||||
Put = 0;
|
||||
// Get refers to object.Get RPC call
|
||||
Get = 1;
|
||||
// Head refers to object.Head RPC call
|
||||
Head = 2;
|
||||
// Search refers to object.Search RPC call
|
||||
Search = 3;
|
||||
// Delete refers to object.Delete RPC call
|
||||
Delete = 4;
|
||||
// Range refers to object.GetRange RPC call
|
||||
Range = 5;
|
||||
// RangeHash refers to object.GetRangeHash RPC call
|
||||
RangeHash = 6;
|
||||
}
|
||||
|
||||
// Verb is a type of request for which the token is issued
|
||||
Verb verb = 3 [(gogoproto.customname) = "Verb"];
|
||||
|
||||
// Address is an object address for which token is issued
|
||||
refs.Address Address = 4 [(gogoproto.nullable) = false, (gogoproto.customtype) = "Address"];
|
||||
|
||||
// Created is an initial epoch of token lifetime
|
||||
uint64 Created = 5;
|
||||
|
||||
// ValidUntil is a last epoch of token lifetime
|
||||
uint64 ValidUntil = 6;
|
||||
|
||||
// SessionKey is a public key of session key
|
||||
bytes SessionKey = 7;
|
||||
}
|
||||
|
||||
// TokenInfo is a grouped information about token
|
||||
Info TokenInfo = 1 [(gogoproto.embed) = true, (gogoproto.nullable) = false];
|
||||
|
||||
// Signature is a signature of session token information
|
||||
bytes Signature = 8;
|
||||
}
|
||||
|
||||
// TODO: for variable token types and version redefine message
|
||||
// Example:
|
||||
// message Token {
|
||||
// TokenType TokenType = 1;
|
||||
// uint32 Version = 2;
|
||||
// bytes Data = 3;
|
||||
// }
|
||||
|
|
|
@ -119,15 +119,13 @@ func TestMaintainableRequest(t *testing.T) {
|
|||
req.TTL--
|
||||
|
||||
key := test.DecodeKey(i)
|
||||
require.NoError(t, SignRequestHeader(key, req))
|
||||
|
||||
// sign first key (session key) by owner key
|
||||
if i == 0 {
|
||||
sign, err := crypto.Sign(owner, crypto.MarshalPublicKey(&key.PublicKey))
|
||||
require.NoError(t, err)
|
||||
|
||||
req.SetOwner(&owner.PublicKey, sign)
|
||||
key = owner
|
||||
}
|
||||
|
||||
require.NoError(t, SignRequestHeader(key, req))
|
||||
}
|
||||
|
||||
{ // Validate owner
|
||||
|
@ -150,17 +148,8 @@ func TestMaintainableRequest(t *testing.T) {
|
|||
require.Equal(t, &owner.PublicKey, pub)
|
||||
}
|
||||
|
||||
{ // wrong owner:
|
||||
req.Signatures[0].Origin = nil
|
||||
|
||||
pub, err := req.GetOwner()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NotEqual(t, &owner.PublicKey, pub)
|
||||
}
|
||||
|
||||
{ // Wrong signatures:
|
||||
copy(req.Signatures[count-1].Sign, req.Signatures[count-1].Peer)
|
||||
copy(req.Signatures[count-1].Sign, req.Signatures[count-2].Sign)
|
||||
err := VerifyRequestHeader(req)
|
||||
require.EqualError(t, errors.Cause(err), crypto.ErrInvalidSignature.Error())
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ import (
|
|||
"crypto/ecdsa"
|
||||
|
||||
"github.com/nspcc-dev/neofs-api-go/refs"
|
||||
crypto "github.com/nspcc-dev/neofs-crypto"
|
||||
)
|
||||
|
||||
type (
|
||||
|
@ -31,9 +30,9 @@ type (
|
|||
TokenParams struct {
|
||||
FirstEpoch uint64
|
||||
LastEpoch uint64
|
||||
ObjectID []ObjectID
|
||||
Address Address
|
||||
OwnerID OwnerID
|
||||
PublicKeys [][]byte
|
||||
Verb Verb
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -46,13 +45,3 @@ func NewInitRequest(t *Token) *CreateRequest {
|
|||
func NewSignedRequest(t *Token) *CreateRequest {
|
||||
return &CreateRequest{Message: &CreateRequest_Signed{Signed: t}}
|
||||
}
|
||||
|
||||
// Sign signs contents of the header with the private key.
|
||||
func (m *VerificationHeader) Sign(key *ecdsa.PrivateKey) error {
|
||||
s, err := crypto.Sign(key, m.PublicKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m.KeySignature = s
|
||||
return nil
|
||||
}
|
||||
|
|
Binary file not shown.
|
@ -3,7 +3,6 @@ package session;
|
|||
option go_package = "github.com/nspcc-dev/neofs-api-go/session";
|
||||
option csharp_namespace = "NeoFS.API.Session";
|
||||
|
||||
import "session/types.proto";
|
||||
import "service/meta.proto";
|
||||
import "service/verify.proto";
|
||||
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
|
||||
|
@ -33,9 +32,9 @@ message CreateRequest {
|
|||
// owner of manipulation object;
|
||||
// ID of manipulation object;
|
||||
// token lifetime bounds.
|
||||
session.Token Init = 1;
|
||||
service.Token Init = 1;
|
||||
// Signed Init message response (Unsigned) from server with user private key
|
||||
session.Token Signed = 2;
|
||||
service.Token Signed = 2;
|
||||
}
|
||||
// RequestMetaHeader contains information about request meta headers (should be embedded into message)
|
||||
service.RequestMetaHeader Meta = 98 [(gogoproto.embed) = true, (gogoproto.nullable) = false];
|
||||
|
@ -46,8 +45,8 @@ message CreateRequest {
|
|||
message CreateResponse {
|
||||
oneof Message {
|
||||
// Unsigned token with token ID and session public key generated on server side
|
||||
session.Token Unsigned = 1;
|
||||
service.Token Unsigned = 1;
|
||||
// Result is a resulting token which can be used for object placing through an trusted intermediary
|
||||
session.Token Result = 2;
|
||||
service.Token Result = 2;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"sync"
|
||||
|
||||
"github.com/nspcc-dev/neofs-api-go/refs"
|
||||
"github.com/nspcc-dev/neofs-api-go/service"
|
||||
crypto "github.com/nspcc-dev/neofs-crypto"
|
||||
)
|
||||
|
||||
|
@ -48,13 +49,15 @@ func (s *simpleStore) New(p TokenParams) *PToken {
|
|||
t := &PToken{
|
||||
mtx: new(sync.Mutex),
|
||||
Token: Token{
|
||||
ID: tid,
|
||||
Header: VerificationHeader{PublicKey: crypto.MarshalPublicKey(&key.PublicKey)},
|
||||
FirstEpoch: p.FirstEpoch,
|
||||
LastEpoch: p.LastEpoch,
|
||||
ObjectID: p.ObjectID,
|
||||
OwnerID: p.OwnerID,
|
||||
PublicKeys: p.PublicKeys,
|
||||
Token_Info: service.Token_Info{
|
||||
ID: tid,
|
||||
OwnerID: p.OwnerID,
|
||||
Verb: p.Verb,
|
||||
Address: p.Address,
|
||||
Created: p.FirstEpoch,
|
||||
ValidUntil: p.LastEpoch,
|
||||
SessionKey: crypto.MarshalPublicKey(&key.PublicKey),
|
||||
},
|
||||
},
|
||||
PrivateKey: key,
|
||||
}
|
||||
|
|
|
@ -1,96 +1,3 @@
|
|||
package session
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/rand"
|
||||
"testing"
|
||||
|
||||
"github.com/nspcc-dev/neofs-api-go/refs"
|
||||
crypto "github.com/nspcc-dev/neofs-crypto"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
type testClient struct {
|
||||
*ecdsa.PrivateKey
|
||||
OwnerID OwnerID
|
||||
}
|
||||
|
||||
func (c *testClient) Sign(data []byte) ([]byte, error) {
|
||||
return crypto.Sign(c.PrivateKey, data)
|
||||
}
|
||||
|
||||
func newTestClient(t *testing.T) *testClient {
|
||||
key, err := ecdsa.GenerateKey(defaultCurve(), rand.Reader)
|
||||
require.NoError(t, err)
|
||||
|
||||
owner, err := refs.NewOwnerID(&key.PublicKey)
|
||||
require.NoError(t, err)
|
||||
|
||||
return &testClient{PrivateKey: key, OwnerID: owner}
|
||||
}
|
||||
|
||||
func signToken(t *testing.T, token *PToken, c *testClient) {
|
||||
require.NotNil(t, token)
|
||||
token.SetPublicKeys(&c.PublicKey)
|
||||
|
||||
signH, err := c.Sign(token.Header.PublicKey)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, signH)
|
||||
|
||||
// data is not yet signed
|
||||
keys := UnmarshalPublicKeys(&token.Token)
|
||||
require.False(t, token.Verify(keys...))
|
||||
|
||||
signT, err := c.Sign(token.verificationData())
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, signT)
|
||||
|
||||
token.AddSignatures(signH, signT)
|
||||
require.True(t, token.Verify(keys...))
|
||||
}
|
||||
|
||||
func TestTokenStore(t *testing.T) {
|
||||
s := NewSimpleStore()
|
||||
|
||||
oid, err := refs.NewObjectID()
|
||||
require.NoError(t, err)
|
||||
|
||||
c := newTestClient(t)
|
||||
require.NotNil(t, c)
|
||||
pk := [][]byte{crypto.MarshalPublicKey(&c.PublicKey)}
|
||||
|
||||
// create new token
|
||||
token := s.New(TokenParams{
|
||||
ObjectID: []ObjectID{oid},
|
||||
OwnerID: c.OwnerID,
|
||||
PublicKeys: pk,
|
||||
})
|
||||
signToken(t, token, c)
|
||||
|
||||
// check that it can be fetched
|
||||
t1 := s.Fetch(token.ID)
|
||||
require.NotNil(t, t1)
|
||||
require.Equal(t, token, t1)
|
||||
|
||||
// create and sign another token by the same client
|
||||
t1 = s.New(TokenParams{
|
||||
ObjectID: []ObjectID{oid},
|
||||
OwnerID: c.OwnerID,
|
||||
PublicKeys: pk,
|
||||
})
|
||||
|
||||
signToken(t, t1, c)
|
||||
|
||||
data := []byte{1, 2, 3}
|
||||
sign, err := t1.SignData(data)
|
||||
require.NoError(t, err)
|
||||
require.Error(t, token.Header.VerifyData(data, sign))
|
||||
|
||||
sign, err = token.SignData(data)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, token.Header.VerifyData(data, sign))
|
||||
|
||||
s.Remove(token.ID)
|
||||
require.Nil(t, s.Fetch(token.ID))
|
||||
require.NotNil(t, s.Fetch(t1.ID))
|
||||
}
|
||||
// TODO: write unit tests
|
||||
|
|
130
session/types.go
130
session/types.go
|
@ -2,14 +2,12 @@ package session
|
|||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"encoding/binary"
|
||||
"sync"
|
||||
|
||||
"github.com/nspcc-dev/neofs-api-go/chain"
|
||||
"github.com/nspcc-dev/neofs-api-go/internal"
|
||||
"github.com/nspcc-dev/neofs-api-go/refs"
|
||||
"github.com/nspcc-dev/neofs-api-go/service"
|
||||
crypto "github.com/nspcc-dev/neofs-crypto"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type (
|
||||
|
@ -19,6 +17,12 @@ type (
|
|||
OwnerID = refs.OwnerID
|
||||
// TokenID type alias.
|
||||
TokenID = refs.UUID
|
||||
// Token type alias
|
||||
Token = service.Token
|
||||
// Address type alias
|
||||
Address = refs.Address
|
||||
// Verb is Token_Info_Verb type alias
|
||||
Verb = service.Token_Info_Verb
|
||||
|
||||
// PToken is a wrapper around Token that allows to sign data
|
||||
// and to do thread-safe manipulations.
|
||||
|
@ -55,127 +59,7 @@ const (
|
|||
ErrInvalidSignature = internal.Error("invalid signature")
|
||||
)
|
||||
|
||||
// verificationData returns byte array to sign.
|
||||
// Note: protobuf serialization is inconsistent as
|
||||
// wire order is unspecified.
|
||||
func (m *Token) verificationData() (data []byte) {
|
||||
var size int
|
||||
if l := len(m.ObjectID); l > 0 {
|
||||
size = m.ObjectID[0].Size()
|
||||
data = make([]byte, 16+l*size)
|
||||
} else {
|
||||
data = make([]byte, 16)
|
||||
}
|
||||
binary.BigEndian.PutUint64(data, m.FirstEpoch)
|
||||
binary.BigEndian.PutUint64(data[8:], m.LastEpoch)
|
||||
for i := range m.ObjectID {
|
||||
copy(data[16+i*size:], m.ObjectID[i].Bytes())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// IsSame checks if the passed token is valid and equal to current token
|
||||
func (m *Token) IsSame(t *Token) error {
|
||||
switch {
|
||||
case m.FirstEpoch != t.FirstEpoch:
|
||||
return ErrWrongFirstEpoch
|
||||
case m.LastEpoch != t.LastEpoch:
|
||||
return ErrWrongLastEpoch
|
||||
case !m.OwnerID.Equal(t.OwnerID):
|
||||
return ErrWrongOwner
|
||||
case m.Header.PublicKey == nil:
|
||||
return ErrEmptyPublicKey
|
||||
case len(m.ObjectID) != len(t.ObjectID):
|
||||
return ErrWrongObjectsCount
|
||||
default:
|
||||
for i := range m.ObjectID {
|
||||
if !m.ObjectID[i].Equal(t.ObjectID[i]) {
|
||||
return errors.Wrapf(ErrWrongObjects, "expect %s, actual: %s", m.ObjectID[i], t.ObjectID[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Sign tries to sign current Token data and stores signature inside it.
|
||||
func (m *Token) Sign(key *ecdsa.PrivateKey) error {
|
||||
if err := m.Header.Sign(key); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s, err := crypto.Sign(key, m.verificationData())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m.Signature = s
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetPublicKeys sets owner's public keys to the token
|
||||
func (m *Token) SetPublicKeys(keys ...*ecdsa.PublicKey) {
|
||||
m.PublicKeys = m.PublicKeys[:0]
|
||||
for i := range keys {
|
||||
m.PublicKeys = append(m.PublicKeys, crypto.MarshalPublicKey(keys[i]))
|
||||
}
|
||||
}
|
||||
|
||||
// Verify checks if token is correct and signed.
|
||||
func (m *Token) Verify(keys ...*ecdsa.PublicKey) bool {
|
||||
if m.FirstEpoch > m.LastEpoch {
|
||||
return false
|
||||
}
|
||||
ownerFromKeys := chain.KeysToAddress(keys...)
|
||||
if m.OwnerID.String() != ownerFromKeys {
|
||||
return false
|
||||
}
|
||||
|
||||
for i := range keys {
|
||||
if m.Header.Verify(keys[i]) && crypto.Verify(keys[i], m.verificationData(), m.Signature) == nil {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// AddSignatures adds token signatures.
|
||||
func (t *PToken) AddSignatures(signH, signT []byte) {
|
||||
t.mtx.Lock()
|
||||
|
||||
t.Header.KeySignature = signH
|
||||
t.Signature = signT
|
||||
|
||||
t.mtx.Unlock()
|
||||
}
|
||||
|
||||
// SignData signs data with session private key.
|
||||
func (t *PToken) SignData(data []byte) ([]byte, error) {
|
||||
return crypto.Sign(t.PrivateKey, data)
|
||||
}
|
||||
|
||||
// VerifyData checks if signature of data by token is equal to sign.
|
||||
func (m *VerificationHeader) VerifyData(data, sign []byte) error {
|
||||
if crypto.Verify(crypto.UnmarshalPublicKey(m.PublicKey), data, sign) != nil {
|
||||
return ErrInvalidSignature
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Verify checks if verification header was issued by id.
|
||||
func (m *VerificationHeader) Verify(keys ...*ecdsa.PublicKey) bool {
|
||||
for i := range keys {
|
||||
if crypto.Verify(keys[i], m.PublicKey, m.KeySignature) == nil {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// UnmarshalPublicKeys returns unmarshal public keys from the token
|
||||
func UnmarshalPublicKeys(t *Token) []*ecdsa.PublicKey {
|
||||
r := make([]*ecdsa.PublicKey, 0, len(t.PublicKeys))
|
||||
for i := range t.PublicKeys {
|
||||
r = append(r, crypto.UnmarshalPublicKey(t.PublicKeys[i]))
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
|
Binary file not shown.
|
@ -1,35 +0,0 @@
|
|||
syntax = "proto3";
|
||||
package session;
|
||||
option go_package = "github.com/nspcc-dev/neofs-api-go/session";
|
||||
option csharp_namespace = "NeoFS.API.Session";
|
||||
|
||||
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
|
||||
|
||||
option (gogoproto.stable_marshaler_all) = true;
|
||||
|
||||
message VerificationHeader {
|
||||
// PublicKey is a session public key
|
||||
bytes PublicKey = 1;
|
||||
// KeySignature is a session public key signature. Signed by trusted side
|
||||
bytes KeySignature = 2;
|
||||
}
|
||||
|
||||
// User token granting rights for object manipulation
|
||||
message Token {
|
||||
// Header carries verification data of session key
|
||||
VerificationHeader Header = 1 [(gogoproto.nullable) = false];
|
||||
// OwnerID is an owner of manipulation object
|
||||
bytes OwnerID = 2 [(gogoproto.customtype) = "OwnerID", (gogoproto.nullable) = false];
|
||||
// FirstEpoch is an initial epoch of token lifetime
|
||||
uint64 FirstEpoch = 3;
|
||||
// LastEpoch is a last epoch of token lifetime
|
||||
uint64 LastEpoch = 4;
|
||||
// ObjectID is an object identifier of manipulation object
|
||||
repeated bytes ObjectID = 5 [(gogoproto.customtype) = "ObjectID", (gogoproto.nullable) = false];
|
||||
// Signature is a token signature, signed by owner of manipulation object
|
||||
bytes Signature = 6;
|
||||
// ID is a token identifier. valid UUIDv4 represented in bytes
|
||||
bytes ID = 7 [(gogoproto.customtype) = "TokenID", (gogoproto.nullable) = false];
|
||||
// PublicKeys associated with owner
|
||||
repeated bytes PublicKeys = 8;
|
||||
}
|
Loading…
Reference in a new issue