2020-04-28 13:58:07 +00:00
|
|
|
package service
|
|
|
|
|
|
|
|
import (
|
2020-04-28 16:03:15 +00:00
|
|
|
"crypto/ecdsa"
|
|
|
|
"encoding/binary"
|
2020-05-05 11:49:35 +00:00
|
|
|
"io"
|
2020-04-28 16:03:15 +00:00
|
|
|
|
2020-05-05 11:49:35 +00:00
|
|
|
"github.com/nspcc-dev/neofs-api-go/refs"
|
2020-04-28 13:58:07 +00:00
|
|
|
)
|
|
|
|
|
2020-05-06 08:44:55 +00:00
|
|
|
type signAccumWithToken struct {
|
|
|
|
SignedDataSource
|
|
|
|
SignKeyPairAccumulator
|
|
|
|
SignKeyPairSource
|
|
|
|
|
|
|
|
token SessionToken
|
|
|
|
}
|
|
|
|
|
|
|
|
type signDataReaderWithToken struct {
|
|
|
|
SignedDataSource
|
|
|
|
SignKeyPairAccumulator
|
|
|
|
SignKeyPairSource
|
|
|
|
|
|
|
|
rdr SignedDataReader
|
|
|
|
|
|
|
|
token SessionToken
|
|
|
|
}
|
|
|
|
|
2020-05-13 15:49:15 +00:00
|
|
|
type signedSessionToken struct {
|
|
|
|
SessionToken
|
|
|
|
}
|
|
|
|
|
2020-05-05 11:49:35 +00:00
|
|
|
const verbSize = 4
|
|
|
|
|
|
|
|
const fixedTokenDataSize = 0 +
|
|
|
|
refs.UUIDSize +
|
|
|
|
refs.OwnerIDSize +
|
|
|
|
verbSize +
|
|
|
|
refs.UUIDSize +
|
|
|
|
refs.CIDSize +
|
|
|
|
8 +
|
|
|
|
8
|
|
|
|
|
2020-04-28 16:03:15 +00:00
|
|
|
var tokenEndianness = binary.BigEndian
|
|
|
|
|
2020-04-28 13:58:07 +00:00
|
|
|
// GetID is an ID field getter.
|
|
|
|
func (m Token_Info) GetID() TokenID {
|
|
|
|
return m.ID
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetID is an ID field setter.
|
|
|
|
func (m *Token_Info) SetID(id TokenID) {
|
|
|
|
m.ID = id
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetOwnerID is an OwnerID field getter.
|
|
|
|
func (m Token_Info) GetOwnerID() OwnerID {
|
|
|
|
return m.OwnerID
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetOwnerID is an OwnerID field setter.
|
|
|
|
func (m *Token_Info) SetOwnerID(id OwnerID) {
|
|
|
|
m.OwnerID = id
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetVerb is a Verb field setter.
|
|
|
|
func (m *Token_Info) SetVerb(verb Token_Info_Verb) {
|
|
|
|
m.Verb = verb
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetAddress is an Address field getter.
|
|
|
|
func (m Token_Info) GetAddress() Address {
|
|
|
|
return m.Address
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetAddress is an Address field setter.
|
|
|
|
func (m *Token_Info) SetAddress(addr Address) {
|
|
|
|
m.Address = addr
|
|
|
|
}
|
|
|
|
|
|
|
|
// CreationEpoch is a Created field getter.
|
2020-05-08 08:08:09 +00:00
|
|
|
func (m TokenLifetime) CreationEpoch() uint64 {
|
2020-04-28 13:58:07 +00:00
|
|
|
return m.Created
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetCreationEpoch is a Created field setter.
|
2020-05-08 08:08:09 +00:00
|
|
|
func (m *TokenLifetime) SetCreationEpoch(e uint64) {
|
2020-04-28 13:58:07 +00:00
|
|
|
m.Created = e
|
|
|
|
}
|
|
|
|
|
|
|
|
// ExpirationEpoch is a ValidUntil field getter.
|
2020-05-08 08:08:09 +00:00
|
|
|
func (m TokenLifetime) ExpirationEpoch() uint64 {
|
2020-04-28 13:58:07 +00:00
|
|
|
return m.ValidUntil
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetExpirationEpoch is a ValidUntil field setter.
|
2020-05-08 08:08:09 +00:00
|
|
|
func (m *TokenLifetime) SetExpirationEpoch(e uint64) {
|
2020-04-28 13:58:07 +00:00
|
|
|
m.ValidUntil = e
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetSessionKey is a SessionKey field setter.
|
|
|
|
func (m *Token_Info) SetSessionKey(key []byte) {
|
|
|
|
m.SessionKey = key
|
|
|
|
}
|
|
|
|
|
2020-05-15 13:03:47 +00:00
|
|
|
// SetOwnerKey is an OwnerKey field setter.
|
|
|
|
func (m *Token_Info) SetOwnerKey(key []byte) {
|
|
|
|
m.OwnerKey = key
|
|
|
|
}
|
|
|
|
|
2020-04-28 13:58:07 +00:00
|
|
|
// SetSignature is a Signature field setter.
|
|
|
|
func (m *Token) SetSignature(sig []byte) {
|
|
|
|
m.Signature = sig
|
|
|
|
}
|
2020-04-28 16:03:15 +00:00
|
|
|
|
2020-05-05 11:49:35 +00:00
|
|
|
// Size returns the size of a binary representation of the verb.
|
|
|
|
func (x Token_Info_Verb) Size() int {
|
|
|
|
return verbSize
|
|
|
|
}
|
2020-04-28 16:03:15 +00:00
|
|
|
|
2020-05-05 11:49:35 +00:00
|
|
|
// Bytes returns a binary representation of the verb.
|
|
|
|
func (x Token_Info_Verb) Bytes() []byte {
|
|
|
|
data := make([]byte, verbSize)
|
|
|
|
tokenEndianness.PutUint32(data, uint32(x))
|
|
|
|
return data
|
|
|
|
}
|
2020-04-28 16:03:15 +00:00
|
|
|
|
2020-05-13 15:49:15 +00:00
|
|
|
// AddSignKey calls a Signature field setter of token with passed signature.
|
|
|
|
func (s signedSessionToken) AddSignKey(sig []byte, _ *ecdsa.PublicKey) {
|
|
|
|
if s.SessionToken != nil {
|
|
|
|
s.SessionToken.SetSignature(sig)
|
|
|
|
}
|
2020-05-05 11:49:35 +00:00
|
|
|
}
|
2020-04-28 16:03:15 +00:00
|
|
|
|
2020-05-05 11:49:35 +00:00
|
|
|
// SignedData returns token information in a binary representation.
|
2020-05-13 15:49:15 +00:00
|
|
|
func (s signedSessionToken) SignedData() ([]byte, error) {
|
|
|
|
return SignedDataFromReader(s)
|
|
|
|
}
|
|
|
|
|
|
|
|
// SignedDataSize returns the length of signed token information slice.
|
|
|
|
func (s signedSessionToken) SignedDataSize() int {
|
|
|
|
return tokenInfoSize(s.SessionToken)
|
2020-05-05 11:49:35 +00:00
|
|
|
}
|
2020-04-28 16:03:15 +00:00
|
|
|
|
2020-05-05 11:49:35 +00:00
|
|
|
// ReadSignedData copies a binary representation of the token information to passed buffer.
|
|
|
|
//
|
|
|
|
// If buffer length is less than required, io.ErrUnexpectedEOF returns.
|
2020-05-13 15:49:15 +00:00
|
|
|
func (s signedSessionToken) ReadSignedData(p []byte) (int, error) {
|
|
|
|
sz := s.SignedDataSize()
|
2020-05-05 11:49:35 +00:00
|
|
|
if len(p) < sz {
|
|
|
|
return 0, io.ErrUnexpectedEOF
|
|
|
|
}
|
2020-04-28 16:03:15 +00:00
|
|
|
|
2020-05-13 15:49:15 +00:00
|
|
|
copyTokenSignedData(p, s.SessionToken)
|
2020-04-28 16:03:15 +00:00
|
|
|
|
2020-05-05 11:49:35 +00:00
|
|
|
return sz, nil
|
|
|
|
}
|
2020-04-28 16:03:15 +00:00
|
|
|
|
2020-05-13 15:49:15 +00:00
|
|
|
// NewSignedSessionToken wraps passed SessionToken in a component suitable for signing.
|
|
|
|
//
|
|
|
|
// Result can be used in AddSignatureWithKey function.
|
|
|
|
func NewSignedSessionToken(token SessionToken) DataWithSignKeyAccumulator {
|
|
|
|
return &signedSessionToken{
|
|
|
|
SessionToken: token,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewVerifiedSessionToken wraps passed SessionToken in a component suitable for signature verification.
|
|
|
|
//
|
|
|
|
// Result can be used in VerifySignatureWithKey function.
|
|
|
|
func NewVerifiedSessionToken(token SessionToken) DataWithSignature {
|
|
|
|
return &signedSessionToken{
|
|
|
|
SessionToken: token,
|
|
|
|
}
|
2020-05-06 08:44:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func tokenInfoSize(v SessionKeySource) int {
|
|
|
|
if v == nil {
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
return fixedTokenDataSize + len(v.GetSessionKey())
|
2020-05-05 11:49:35 +00:00
|
|
|
}
|
2020-04-28 16:03:15 +00:00
|
|
|
|
2020-05-05 11:49:35 +00:00
|
|
|
// Fills passed buffer with signing token information bytes.
|
|
|
|
// Does not check buffer length, it is understood that enough space is allocated in it.
|
2020-05-06 08:44:55 +00:00
|
|
|
//
|
|
|
|
// If passed SessionTokenInfo, buffer remains unchanged.
|
2020-05-05 11:49:35 +00:00
|
|
|
func copyTokenSignedData(buf []byte, token SessionTokenInfo) {
|
2020-05-06 08:44:55 +00:00
|
|
|
if token == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-05-05 11:49:35 +00:00
|
|
|
var off int
|
2020-04-28 16:03:15 +00:00
|
|
|
|
2020-05-05 11:49:35 +00:00
|
|
|
off += copy(buf[off:], token.GetID().Bytes())
|
2020-04-28 16:03:15 +00:00
|
|
|
|
2020-05-05 11:49:35 +00:00
|
|
|
off += copy(buf[off:], token.GetOwnerID().Bytes())
|
2020-04-28 16:03:15 +00:00
|
|
|
|
2020-05-05 11:49:35 +00:00
|
|
|
off += copy(buf[off:], token.GetVerb().Bytes())
|
2020-04-28 16:03:15 +00:00
|
|
|
|
2020-05-05 11:49:35 +00:00
|
|
|
addr := token.GetAddress()
|
|
|
|
off += copy(buf[off:], addr.CID.Bytes())
|
|
|
|
off += copy(buf[off:], addr.ObjectID.Bytes())
|
2020-04-28 16:03:15 +00:00
|
|
|
|
2020-05-05 11:49:35 +00:00
|
|
|
tokenEndianness.PutUint64(buf[off:], token.CreationEpoch())
|
|
|
|
off += 8
|
2020-04-28 16:03:15 +00:00
|
|
|
|
2020-05-05 11:49:35 +00:00
|
|
|
tokenEndianness.PutUint64(buf[off:], token.ExpirationEpoch())
|
|
|
|
off += 8
|
2020-04-29 07:57:07 +00:00
|
|
|
|
2020-05-05 11:49:35 +00:00
|
|
|
copy(buf[off:], token.GetSessionKey())
|
2020-04-28 16:03:15 +00:00
|
|
|
}
|
2020-05-06 08:44:55 +00:00
|
|
|
|
|
|
|
// SignedData concatenates signed data with session token information. Returns concatenation result.
|
|
|
|
//
|
|
|
|
// Token bytes are added if and only if token is not nil.
|
|
|
|
func (s signAccumWithToken) SignedData() ([]byte, error) {
|
|
|
|
data, err := s.SignedDataSource.SignedData()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
tokenData := make([]byte, tokenInfoSize(s.token))
|
|
|
|
|
|
|
|
copyTokenSignedData(tokenData, s.token)
|
|
|
|
|
|
|
|
return append(data, tokenData...), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s signDataReaderWithToken) SignedDataSize() int {
|
|
|
|
sz := s.rdr.SignedDataSize()
|
|
|
|
if sz < 0 {
|
|
|
|
return -1
|
|
|
|
}
|
|
|
|
|
|
|
|
sz += tokenInfoSize(s.token)
|
|
|
|
|
|
|
|
return sz
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s signDataReaderWithToken) ReadSignedData(p []byte) (int, error) {
|
|
|
|
dataSize := s.rdr.SignedDataSize()
|
|
|
|
if dataSize < 0 {
|
|
|
|
return 0, ErrNegativeLength
|
|
|
|
}
|
|
|
|
|
|
|
|
sumSize := dataSize + tokenInfoSize(s.token)
|
|
|
|
|
|
|
|
if len(p) < sumSize {
|
|
|
|
return 0, io.ErrUnexpectedEOF
|
|
|
|
}
|
|
|
|
|
|
|
|
if n, err := s.rdr.ReadSignedData(p); err != nil {
|
|
|
|
return n, err
|
|
|
|
}
|
|
|
|
|
|
|
|
copyTokenSignedData(p[dataSize:], s.token)
|
|
|
|
|
|
|
|
return sumSize, nil
|
|
|
|
}
|