Skip to content

Commit 9aaa6a2

Browse files
committed
sn/object: Do not add session token to EC part
The session token is in the parent object, but in the part it is meaningless. Moreover, if the part object needs to be recreated, the session token will no longer exist. Therefore, not adding a token preserves the object ID which is good for deduplication. For this to work, it was necessary to make an exception when checking the signature against the object owner. Refs #3628. Signed-off-by: Leonard Lyubich <[email protected]>
1 parent 3404e20 commit 9aaa6a2

File tree

8 files changed

+37
-18
lines changed

8 files changed

+37
-18
lines changed

internal/crypto/object.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import (
1313
)
1414

1515
// AuthenticateObject checks whether obj is signed correctly by its owner.
16-
func AuthenticateObject(obj object.Object, fsChain HistoricN3ScriptRunner) error {
16+
func AuthenticateObject(obj object.Object, fsChain HistoricN3ScriptRunner, ecPart bool) error {
1717
sig := obj.Signature()
1818
if sig == nil {
1919
return errMissingSignature
@@ -57,7 +57,7 @@ func AuthenticateObject(obj object.Object, fsChain HistoricN3ScriptRunner) error
5757
if !verifyECDSAFns[scheme](*ecdsaPub, sig.Value(), obj.GetID().Marshal()) {
5858
return schemeError(scheme, errSignatureMismatch)
5959
}
60-
if sessionToken == nil && user.NewFromECDSAPublicKey(*ecdsaPub) != obj.Owner() {
60+
if sessionToken == nil && !ecPart && user.NewFromECDSAPublicKey(*ecdsaPub) != obj.Owner() {
6161
return errors.New("owner mismatches signature")
6262
}
6363
case neofscrypto.N3:

internal/crypto/object_test.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,14 @@ import (
2020
func TestAuthenticateObject(t *testing.T) {
2121
t.Run("without signature", func(t *testing.T) {
2222
obj := getUnsignedObject()
23-
require.EqualError(t, icrypto.AuthenticateObject(obj, nil), "missing signature")
23+
require.EqualError(t, icrypto.AuthenticateObject(obj, nil, false), "missing signature")
2424
})
2525
t.Run("unsupported scheme", func(t *testing.T) {
2626
obj := objectECDSASHA512
2727
sig := *obj.Signature()
2828
sig.SetScheme(4)
2929
obj.SetSignature(&sig)
30-
require.EqualError(t, icrypto.AuthenticateObject(obj, nil), "unsupported scheme 4")
30+
require.EqualError(t, icrypto.AuthenticateObject(obj, nil, false), "unsupported scheme 4")
3131
})
3232
t.Run("invalid public key", func(t *testing.T) {
3333
for _, tc := range []struct {
@@ -48,7 +48,7 @@ func TestAuthenticateObject(t *testing.T) {
4848
sig := *obj.Signature()
4949
sig.SetPublicKeyBytes(tc.changePub(sig.PublicKeyBytes()))
5050
obj.SetSignature(&sig)
51-
err := icrypto.AuthenticateObject(obj, nil)
51+
err := icrypto.AuthenticateObject(obj, nil, false)
5252
require.EqualError(t, err, "scheme ECDSA_SHA512: decode public key: "+tc.err)
5353
})
5454
}
@@ -70,7 +70,7 @@ func TestAuthenticateObject(t *testing.T) {
7070
cp[i]++
7171
sig.SetValue(cp)
7272
tc.obj.SetSignature(&sig)
73-
err := icrypto.AuthenticateObject(tc.obj, nil)
73+
err := icrypto.AuthenticateObject(tc.obj, nil, false)
7474
require.EqualError(t, err, fmt.Sprintf("scheme %s: signature mismatch", tc.scheme))
7575
}
7676
})
@@ -86,7 +86,7 @@ func TestAuthenticateObject(t *testing.T) {
8686
{scheme: neofscrypto.ECDSA_WALLETCONNECT, object: wrongOwnerObjectECDSAWalletConnect},
8787
} {
8888
t.Run(tc.scheme.String(), func(t *testing.T) {
89-
require.EqualError(t, icrypto.AuthenticateObject(tc.object, nil), "owner mismatches signature")
89+
require.EqualError(t, icrypto.AuthenticateObject(tc.object, nil, false), "owner mismatches signature")
9090
})
9191
}
9292
})
@@ -101,7 +101,7 @@ func TestAuthenticateObject(t *testing.T) {
101101
{scheme: neofscrypto.ECDSA_WALLETCONNECT, object: objectWithNoIssuerSessionECDSAWalletConnect},
102102
} {
103103
t.Run(tc.scheme.String(), func(t *testing.T) {
104-
require.EqualError(t, icrypto.AuthenticateObject(tc.object, nil), "session token: missing issuer")
104+
require.EqualError(t, icrypto.AuthenticateObject(tc.object, nil, false), "session token: missing issuer")
105105
})
106106
}
107107
})
@@ -115,7 +115,7 @@ func TestAuthenticateObject(t *testing.T) {
115115
{scheme: neofscrypto.ECDSA_WALLETCONNECT, object: objectWithWrongIssuerSessionECDSAWalletConnect},
116116
} {
117117
t.Run(tc.scheme.String(), func(t *testing.T) {
118-
require.EqualError(t, icrypto.AuthenticateObject(tc.object, nil), "session token: issuer mismatches signature")
118+
require.EqualError(t, icrypto.AuthenticateObject(tc.object, nil, false), "session token: issuer mismatches signature")
119119
})
120120
}
121121
})
@@ -129,7 +129,7 @@ func TestAuthenticateObject(t *testing.T) {
129129
{scheme: neofscrypto.ECDSA_WALLETCONNECT, object: objectWithWrongSessionSubjectECDSAWalletConnect},
130130
} {
131131
t.Run(tc.scheme.String(), func(t *testing.T) {
132-
require.EqualError(t, icrypto.AuthenticateObject(tc.object, nil), "session token is not for object's signer")
132+
require.EqualError(t, icrypto.AuthenticateObject(tc.object, nil, false), "session token is not for object's signer")
133133
})
134134
}
135135
})
@@ -143,7 +143,7 @@ func TestAuthenticateObject(t *testing.T) {
143143
{scheme: neofscrypto.ECDSA_WALLETCONNECT, object: objectWithWrongOwnerSessionECDSAWalletConnect},
144144
} {
145145
t.Run(tc.scheme.String(), func(t *testing.T) {
146-
require.EqualError(t, icrypto.AuthenticateObject(tc.object, nil), "different object owner and session issuer")
146+
require.EqualError(t, icrypto.AuthenticateObject(tc.object, nil, false), "different object owner and session issuer")
147147
})
148148
}
149149
})
@@ -160,7 +160,7 @@ func TestAuthenticateObject(t *testing.T) {
160160
{name: neofscrypto.ECDSA_WALLETCONNECT.String() + " with session", object: objectWithSessionECDSAWalletConnect},
161161
} {
162162
t.Run(tc.name, func(t *testing.T) {
163-
require.NoError(t, icrypto.AuthenticateObject(tc.object, nil))
163+
require.NoError(t, icrypto.AuthenticateObject(tc.object, nil, false))
164164
})
165165
}
166166
}

internal/ec/object_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ func TestFormObjectForECPart(t *testing.T) {
149149
require.Equal(t, parent.Owner(), obj.Owner())
150150
require.Equal(t, parent.CreationEpoch(), obj.CreationEpoch())
151151
require.Equal(t, object.TypeRegular, obj.Type())
152-
require.Equal(t, parent.SessionToken(), obj.SessionToken())
152+
require.Zero(t, obj.SessionToken())
153153

154154
_, ok = obj.PayloadHomomorphicHash()
155155
require.False(t, ok)

internal/ec/objects.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ func FormObjectForECPart(signer neofscrypto.Signer, parent object.Object, part [
7272
obj.SetOwner(parent.Owner())
7373
obj.SetCreationEpoch(parent.CreationEpoch())
7474
obj.SetType(object.TypeRegular)
75-
obj.SetSessionToken(parent.SessionToken())
7675

7776
obj.SetParent(&parent)
7877
iobject.SetIntAttribute(&obj, AttributeRuleIdx, partInfo.RuleIndex)

pkg/core/object/ec.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ func checkEC(hdr object.Object, rules []netmap.ECRule, blank bool, isParent bool
7373
}
7474

7575
func checkECPart(part object.Object, rules []netmap.ECRule) error {
76+
if part.SessionToken() != nil {
77+
return errors.New("session token detected")
78+
}
79+
7680
parent := part.Parent()
7781
if parent == nil {
7882
return errors.New("missing parent header")

pkg/core/object/ec_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test"
1212
"github.com/nspcc-dev/neofs-sdk-go/netmap"
1313
"github.com/nspcc-dev/neofs-sdk-go/object"
14+
"github.com/nspcc-dev/neofs-sdk-go/session"
1415
usertest "github.com/nspcc-dev/neofs-sdk-go/user/test"
1516
"github.com/nspcc-dev/neofs-sdk-go/version"
1617
"github.com/stretchr/testify/require"
@@ -193,6 +194,9 @@ func TestFormatValidator_Validate_EC(t *testing.T) {
193194
{name: "wrong payload len", err: "invalid regular EC part object: wrong part payload len: expected 342, got 343, parent 4096", corruptPart: func(obj *object.Object) {
194195
obj.SetPayloadSize(343)
195196
}},
197+
{name: "session token in part", err: "invalid regular EC part object: session token detected", corruptPart: func(obj *object.Object) {
198+
obj.SetSessionToken(new(session.Object))
199+
}},
196200
} {
197201
t.Run(tc.name, func(t *testing.T) {
198202
if tc.corruptParent != nil {
@@ -249,6 +253,19 @@ func TestFormatValidator_Validate_EC(t *testing.T) {
249253
require.EqualError(t, v.Validate(&cp, false), "object with EC attributes __NEOFS__EC_RULE_IDX in container without EC rules")
250254
})
251255

256+
t.Run("part created by 3rd party", func(t *testing.T) {
257+
otherCreator := usertest.User()
258+
for i := range parts {
259+
obj, err := iec.FormObjectForECPart(otherCreator, parent, parts[i], iec.PartInfo{
260+
RuleIndex: ruleIdx,
261+
Index: i,
262+
})
263+
require.NoError(t, err)
264+
265+
require.NoError(t, v.Validate(&obj, false))
266+
}
267+
})
268+
252269
for i := range ecParts {
253270
require.NoError(t, v.Validate(&ecParts[i], false))
254271
}

pkg/core/object/fmt.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ func (v *FormatValidator) validate(obj *object.Object, unprepared, isParent bool
235235
if err := icrypto.AuthenticateObject(*obj, historicN3ScriptRunner{
236236
FSChain: v.fsChain,
237237
NetmapContract: v.netmapContract,
238-
}); err != nil {
238+
}, isEC); err != nil {
239239
return fmt.Errorf("authenticate: %w", err)
240240
}
241241

pkg/services/object/put/service_test.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -977,8 +977,6 @@ func assertObjectIntegrity(t *testing.T, obj object.Object) {
977977

978978
require.NotZero(t, obj.Owner())
979979

980-
require.NotZero(t, obj.SessionToken())
981-
982980
payload := obj.Payload()
983981
require.EqualValues(t, obj.PayloadSize(), len(payload))
984982

@@ -1004,6 +1002,7 @@ func checkAndGetObjectFromECParts(t *testing.T, limit uint64, rule iec.Rule, par
10041002

10051003
for _, part := range parts {
10061004
assertObjectIntegrity(t, part)
1005+
require.Zero(t, part.SessionToken())
10071006
require.LessOrEqual(t, part.PayloadSize(), limit)
10081007
}
10091008

@@ -1080,7 +1079,7 @@ func checkAndCutParentHeaderFromECPart(t *testing.T, part object.Object) object.
10801079
require.Equal(t, par.Owner(), part.Owner())
10811080
require.Equal(t, par.CreationEpoch(), part.CreationEpoch())
10821081
require.Equal(t, object.TypeRegular, part.Type())
1083-
require.Equal(t, par.SessionToken(), part.SessionToken())
1082+
require.NotZero(t, par.SessionToken())
10841083

10851084
return *par
10861085
}

0 commit comments

Comments
 (0)