From d5072d20f09489be796a1b8b90cc7a340df6ca22 Mon Sep 17 00:00:00 2001 From: alexvanin Date: Wed, 15 Jan 2020 17:05:53 +0300 Subject: [PATCH 01/12] docs: Add doc for container ACL field ACL support still under development. Detailed documentation on container access rules will be added later. --- docs/container.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/docs/container.md b/docs/container.md index ef2ba19..6693980 100644 --- a/docs/container.md +++ b/docs/container.md @@ -21,6 +21,8 @@ - [container/types.proto](#container/types.proto) - Messages + - [AccessControlList](#container.AccessControlList) + - [AccessGroup](#container.AccessGroup) - [Container](#container.Container) @@ -164,6 +166,7 @@ via consensus in inner ring nodes | Capacity | [uint64](#uint64) | | Capacity defines amount of data that can be stored in the container (doesn't used for now). | | OwnerID | [bytes](#bytes) | | OwnerID is a wallet address | | rules | [netmap.PlacementRule](#netmap.PlacementRule) | | Rules define storage policy for the object inside the container. | +| Group | [AccessGroup](#container.AccessGroup) | | Container ACL. | | 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) | @@ -193,6 +196,29 @@ via consensus in inner ring nodes + + +### Message AccessControlList + + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| List | [AccessGroup](#container.AccessGroup) | repeated | List of access groups. | + + + + +### Message AccessGroup + + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| AccessMode | [uint32](#uint32) | | Group access mode. | +| UserGroup | [bytes](#bytes) | repeated | Group members. | + + ### Message Container @@ -205,6 +231,7 @@ The Container service definition. | Salt | [bytes](#bytes) | | Salt is a nonce for unique container id calculation. | | Capacity | [uint64](#uint64) | | Capacity defines amount of data that can be stored in the container (doesn't used for now). | | Rules | [netmap.PlacementRule](#netmap.PlacementRule) | | Rules define storage policy for the object inside the container. | +| List | [AccessControlList](#container.AccessControlList) | | Container ACL. | From e4d761be06c4acfd1767e476b43614320bd03aa6 Mon Sep 17 00:00:00 2001 From: alexvanin Date: Wed, 15 Jan 2020 17:10:45 +0300 Subject: [PATCH 02/12] object: Remove tombstone creation field in tombstone header Tombstone header contains timestamp when tombstone was created. This timestamp duplicates object creation timestamp in object system header. This commit removes redundant field. --- object/types.pb.go | Bin 79938 -> 79138 bytes object/types.proto | 5 +---- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/object/types.pb.go b/object/types.pb.go index 459e124b053ab4c032498513b277709a36b089bb..b5a1e785e86633310ad63204e2a52d2b49da629d 100644 GIT binary patch delta 5256 zcmY+IJIh@~6ov^2hC~z_wJ=IR5E2sD_X~nzXDJ9`VY9DIKm?mp2)hnea~S-a+WCU|TnJ9B2%?Op3#Yrfx~-}v$G8_(XmcmD2;ch0YT@aX)_!re*dlOSARadfA3m-{^zr=k7a&vw>S-3TDLl_P4nRPt>RQR=|6Lu){-B#K7IG> zcyt`o&fal`^9v`tBJC8M9Lx0Gp`hh_y`W&6;)mlj@OzJp0b@$euE-dM|0Ma{@N0oB z8+YATPS(?+q2ANw64Bd|zDL#>p<9K1{T$cybBhlRcDGvZirowAi2iCvgN`m7GKMQU z4NS#;gHtu4vx8XF>3@y90dHF_H-78GY;XzdjHC|NYxY~#72|t;T{I6#ASM`ZoVWeK5&oz%sxrO}Yut!$6HU(rnv^|l z2wF*~8C!ZQ+DbFHrgFj0EuzKE>~SqC^jAm<+6kQ%-WJ4d!xM{mtnfiPl2W9MnF}pm zO@;??(ub99dPrZDX~4;@L4OI{K@AB8tzRUq3%D~F1iB$Sg}|V>W`DupiJbwVLT_bm z^6EhJWWu68lG6>=NI@oXWr48P=rKL4m06&%QCqCi2p-IhF{!#ZdQZp zW&n^ICAI+>GQK1$rT17gTMYzEol;4!b?ifX#Yz5b4)!7u!T`HTW$|OB)Uab-hX#Ss z6YFE)Zil5SfJJ%&13zfI8EdO4G!m1FgMXx*_M#3qXw~H;uLz(V-@bmo}{5681^*H zt1xv(s{P2^vlHm84P5^0u*;gv?2cVWa7of&Ly$~6EOV%FM|oDA6(FUzz+jRX&)Iat zLwkKpWJ!U+$V|gECXOQ)Vjju3*8zYRL@c)pg5+3WhpXoqeB8L`LDOcys)C1i#*(cAx7C$puk;PA6&3*3hR)aAhtMZ)k|W&8-y*$ zGPxk5#AKf4FJ~U7D)ZgSozY{yE7g~Y=_^?&Tkx#dm@JY8*;mmTV=4C-Y3phS^qWMb z)QO)t>!l;C7|9!7CP7w7gC)Z&>Xct5L^31Ew?kzm`5;=(cAAP2CHZgHwkY&A$|PxU zxX$kv4Uh=QK-;oB?Qr1ZuL6urjocEj-MYo8+7>;}%pWUhBEM^fHQNy@#{z@vAmPkq zJZ+uQt`A{JHe@Cjd^knF4nLiU?~_Lz-66HN~XlH4b# zDyz|qtz-U8KKN#7kfD`Qjc-P4Jm)9iI$TS2LS>TpD7Dgh>GN`&%w>%l+vRrX&qcp> z^dGHmEcPvBq6xQP*hhm=fB}ee%SC7h7(U-*G+nT)9r>DrYvzZOq*Gw-Xhm%N~4rtba*upl7UtIj_NXs zuZKKlSnpP&3hWAwc@D3K1HCVr{5Ir99=-XF-j&M7D&gBX&u(fmyl_EkV9leY;~c9k zQXk%;~Jsoc+BJi2qIK)C(F zK~wWnMqT~z==-I@ X`t|AE4}bgg+O@x~UA_PO=Ewg6&K53L delta 5357 zcmZXYO^Y2>5QYf}$YdabAcCR{h(dJK{_cAb(T%8k5x4zG5H(@~xw~Gt(S@K~!IdDo zl_<=@oeO`CAjDswb)M%$2i!D$`Kd?uU$R!IP`UT&SQEu&H43{;!y6=kA0V(U6Y>cK0OyU zjct0LtMnY$+3>w$PdTLTH9~7w%k*X9OVgvEN()<37b_*_TIB6HQ7q|u(X+~z<xQsrp~=eLtaLvlMhxv3m67>_ArJ? zM6LM&gu-L)yK^)FcuouY4fnblXrad#Y0Ns92$^(b#u{|Z>(FWF2PDX-3m_Gs5S5%< zD1fH`fL*(#s@y3Xn`WLR=T;Mk_m+35aYCL{YuZ@*gBn&0Fas2{7#NOq2(px>68#M^ zajSM$m}f$Dpe;>Bc>eRD#q1h+D+iRVsTTB()s9@Pv8%zIheFXWLC9hey`(`35NOFS zx<)|N;)61Bhr+ks?70+N$xmL*I@uGhB?UEt){SU1oEz}RwEDM?gw7J*w4x>5>_jvB zN9>Xm?F~bT1_d>2vg$@^Vu!L|t`J>sEL$K(%tj?C)oRdG4omMrllXw^nvnxa9Vp1g ztJ&s?G-(4b(BE%XG+vo*CTqknX|QJZg6mcQ6Oz`dGxx1)-fhe3*I=_+vap70S#Qe? zRv1W@T+!&XgU8-fC4|AS26M$1lSq)P0K?OhVv(4*plA-*>PEbc4jv*l6USJ|6ZGXn zA-%FmA{_ACdYeVTF~g}P7m>L_tR~!%>u0h=7<6G&f6Id1X9T^9$hdVcN@k<VgQ1gMJnc|H;PE9aN*ZKh=K@>QU zkP;*2FS0@A>cB+8x63o69>QBR5Gxm)e00>3)wkf_FiC23YU)YA2{m>UvznN12bm+! zlQFm^7Xi+v$>J#8vg((G_ZDrA)dd>tZ*ojQAY;x8nK9ob7mTF9q-i(i534wOaqJ={ z2hTa$DAk@O^s<5N+SVx%$C#BgxS&!GJ3BNOd|5#sS(@fA(}d-$0lS?=b4ubvFdZ5Q zXl5&mg-X*%>)O^O`Q>&=@bc_}ghYg)-?`nXI+!zQFdNK$Gf;n&ZJ)3cSxfde)7tvT zOhf2<(-44b=a`a(Nc}W_Ijr09Bxk#3nva8mIb8wI3@{F=Udtw_T%`_tHL|I3PgCszC0fHp50qG~m2Ma5yS0gcS< z1u>7C1U-`sW1CH@mwbT1_k6{2{>-;x@NvR*go~z;P%`UH9B=vRwC{NZF3Ak*CU+Se zkqvri%3(tK(#CGs&=9Uf;2affg?l`a-@Po@L7mi00~>#|$T;g4WqW(D@5cA!LXCOi zX5l&`ts73;1FTu6)J(n>4z}2RR#46Lj^-$(q#=gBR7wx?I^LbtC5r(OGN(}aw?ntF zU_QrPx8efw`e@^?+O9XFsGJ(%O^qNWPt)XUJ`3DJCBwdk%@mck`Dr4XYmgf z|Jl$CiBKZScW``Gl6Xq^dA25~-oQc*AW@WgB*d^yJ&q@WYnSt%l3WddZm;pOIC9wk zEKIIwGD(B#yooOuVA)FqGO@P`Z!DXjiFo96_rE>)ZSnY(H-5c;?aE_UFP{4Ik+=T=IdV+F diff --git a/object/types.proto b/object/types.proto index d2bbaab..8f50f76 100644 --- a/object/types.proto +++ b/object/types.proto @@ -48,10 +48,7 @@ message Header { } } -message Tombstone { - // Epoch when tombstone was created - uint64 Epoch = 1; -} +message Tombstone {} message SystemHeader { // Version of the object structure From dea70026259ea7a6de540db24682bfafcdc6abbf Mon Sep 17 00:00:00 2001 From: alexvanin Date: Wed, 15 Jan 2020 17:11:39 +0300 Subject: [PATCH 03/12] docs: Update doc for object proto file Tombstone header in the object does not contain timestamp now. --- docs/object.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/docs/object.md b/docs/object.md index 9e7efe6..e9248ba 100644 --- a/docs/object.md +++ b/docs/object.md @@ -441,10 +441,6 @@ in distributed system. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| Epoch | [uint64](#uint64) | | Epoch when tombstone was created | - From f0097d6c248f301f1f9ff8cc31355662ddbf36fd Mon Sep 17 00:00:00 2001 From: alexvanin Date: Thu, 16 Jan 2020 14:16:20 +0300 Subject: [PATCH 04/12] dep: Update neofs-crypto lib to v0.2.3 --- go.mod | 2 +- go.sum | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index bb8c4ff..688905e 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/golang/protobuf v1.3.2 github.com/google/uuid v1.1.1 github.com/mr-tron/base58 v1.1.3 - github.com/nspcc-dev/neofs-crypto v0.2.2 + github.com/nspcc-dev/neofs-crypto v0.2.3 github.com/nspcc-dev/netmap v1.6.1 github.com/nspcc-dev/tzhash v1.3.0 github.com/pkg/errors v0.8.1 diff --git a/go.sum b/go.sum index db7763e..531a682 100644 --- a/go.sum +++ b/go.sum @@ -106,12 +106,12 @@ github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjW github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nspcc-dev/hrw v1.0.8 h1:vwRuJXZXgkMvf473vFzeWGCfY1WBVeSHAEHvR4u3/Cg= github.com/nspcc-dev/hrw v1.0.8/go.mod h1:l/W2vx83vMQo6aStyx2AuZrJ+07lGv2JQGlVkPG06MU= -github.com/nspcc-dev/neofs-crypto v0.2.2 h1:jLc5O+Wdpaq7L4lNYFX7li+OP4I1FsvvcPW1NXm3erY= -github.com/nspcc-dev/neofs-crypto v0.2.2/go.mod h1:F/96fUzPM3wR+UGsPi3faVNmFlA9KAEAUQR7dMxZmNA= +github.com/nspcc-dev/neofs-crypto v0.2.3 h1:aca3X2aly92ENRbFK+kH6Hd+J9EQ4Eu6XMVoITSIKtc= +github.com/nspcc-dev/neofs-crypto v0.2.3/go.mod h1:8w16GEJbH6791ktVqHN9YRNH3s9BEEKYxGhlFnp0cDw= github.com/nspcc-dev/netmap v1.6.1 h1:Pigqpqi6QSdRiusbq5XlO20A18k6Eyu7j9MzOfAE3CM= github.com/nspcc-dev/netmap v1.6.1/go.mod h1:mhV3UOg9ljQmu0teQShD6+JYX09XY5gu2I4hIByCH9M= -github.com/nspcc-dev/rfc6979 v0.1.0 h1:Lwg7esRRoyK1Up/IN1vAef1EmvrBeMHeeEkek2fAJ6c= -github.com/nspcc-dev/rfc6979 v0.1.0/go.mod h1:exhIh1PdpDC5vQmyEsGvc4YDM/lyQp/452QxGq/UEso= +github.com/nspcc-dev/rfc6979 v0.2.0 h1:3e1WNxrN60/6N0DW7+UYisLeZJyfqZTNOjeV/toYvOE= +github.com/nspcc-dev/rfc6979 v0.2.0/go.mod h1:exhIh1PdpDC5vQmyEsGvc4YDM/lyQp/452QxGq/UEso= github.com/nspcc-dev/tzhash v1.3.0 h1:n6FTHsfPYbMi5Jmo6SwGVVRQD8i2w1P2ScCaW6rz69Q= github.com/nspcc-dev/tzhash v1.3.0/go.mod h1:Lc4DersKS8MNIrunTmsAzANO56qnG+LZ4GOE/WYGVzU= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= From 50d3649acf2143125b1eb1fece68b43c091596c5 Mon Sep 17 00:00:00 2001 From: alexvanin Date: Thu, 16 Jan 2020 14:17:34 +0300 Subject: [PATCH 05/12] object: Add public key header type Object can contain public key header. It will be used for object verification. This header can contain owner's public key or be the part of x509 chain verification in couple with verification header. --- object/types.go | 6 ++++++ object/types.pb.go | Bin 79138 -> 85248 bytes object/types.proto | 7 +++++++ 3 files changed, 13 insertions(+) diff --git a/object/types.go b/object/types.go index f433b9c..79cef65 100644 --- a/object/types.go +++ b/object/types.go @@ -67,6 +67,8 @@ const ( IntegrityHdr // StorageGroupHdr is a storage group header type. StorageGroupHdr + // PublicKeyHdr is a public key header type. + PublicKeyHdr ) var ( @@ -140,6 +142,8 @@ func (m Header) typeOf(t isHeader_Value) (ok bool) { _, ok = m.Value.(*Header_Integrity) case *Header_StorageGroup: _, ok = m.Value.(*Header_StorageGroup) + case *Header_PublicKey: + _, ok = m.Value.(*Header_PublicKey) } return } @@ -168,6 +172,8 @@ func HeaderType(t headerType) Pred { return func(h *Header) bool { _, ok := h.Value.(*Header_Integrity); return ok } case StorageGroupHdr: return func(h *Header) bool { _, ok := h.Value.(*Header_StorageGroup); return ok } + case PublicKeyHdr: + return func(h *Header) bool { _, ok := h.Value.(*Header_PublicKey); return ok } default: return nil } diff --git a/object/types.pb.go b/object/types.pb.go index b5a1e785e86633310ad63204e2a52d2b49da629d..525b39b3b8b633290cdfab4649036dd57a343266 100644 GIT binary patch delta 6481 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 delta 5255 zcmY+IJ*yp66o$FMsL2J(K(q;h5GBH#`JT>33&F}p&}Kft&U8mXMmxJC+|JU%#wKtg zDa1k){1vtqmUbedYd_Bp9Gkgw_w2pC-nHJf_W9!L>)-tG+~fCeoj$(x^NrJ!JO5ss zet-47>!%;?etU8H{EaVPKmGc_-`B4G`S8)Twz_)w(WiUA-n&yA*D5{h`rgeO#qm(5 zf2Jlq4}4g=^xm=J)?r91Tgx8y&+KfAv{JBhIHdO$1r7VF83n_bKJ@AHe(aFZPig7E z-US(bpH`IQd(GDZTUKPdj-Y3H8Z=ZJ;t;*g>3!fiA#^SIn#|sh!;=1K@S(=;M(cfI z_snxZf4QMSM`tz}!v&oNrewXwsS45AK`d(Vze?ivV~@8Dhil*UVKTUcbwW~$>lNz_ z&jsT6$SevYzgN+bnXEws z&}lwZe63@D=y$6*Iby|(50PR-iNFQwDH{oKgE3~qrdO`;G>1p_j|eJxR_ruat%iug z%{_3~(4eg)mYFgg!JUa%<7u91sHuProgES?VlkL{tZV}=Sf(0moL9^Xm3w#;^~ zi4W3|lp zVtq!>$VyKR3B8rM%Bwv=68l1N<(^!Zf=uGl0^wPq$Mi_W5~PgX6*g*%RT{yAxshsh z3A)9Vc@@J7YmzMKEA-FAL}D+Ej2d{?w^`0`>j4=;JmR|i8IFdL=7&@hA&!*;+71Zu|8(bwph9VSa<~te9(9uwWSssiAe>|Vb?wq*E%qL#ckoM8V)qq2*y9k36*zvAEGgb(O9Y=#@Yx|BJ zDw7raw~RBQcWWm14$?OaNTJ6EQ>_QbxeY%!yN-IJ3V3uw5q31;UbW zNA@HQHRtSUnpa}#h7a~5bI(qow>EJ3v&AlJGP65&1(k$?{b)mwOj|5-sBuMk&RJG~ zl->YCApqDinQnM!uaC(uxnMAQqAI&OaZrb$Ut~Df0)PiZEVm2U01b8s8+A~6(%>eW zpdpqN%vcdFG1#yj2*8>GxgS@8KBHgFrnvnr#sXj<8!Nz&abE`$$tagrxlyD-IL`+Ffwa#LTaX#A`?KjOo>CdyF zza_*%EZpY1Lw7^m@@y>_L}ZpSB)s#2uZ$|s+=&RJLuEoT^jqncgBa#PpRLYri7z|fTdY0^c&A;$Y{V;!PtNyM%fe|96eYcfMnfB<972P zw%BRaOJd#|ge}N2DUeZ|%%f|k`OB%we7ABZ^ys=$y_uN4l9jRr&x(!7B59C)9j7$L zQtmL@*42;1n7KPqMnIsK)R<-46fJ8_J+Lq;MhXXH}rTe8uP6^m%-2zX{P6SD+UztDTcg?V7 zTVmx{U~nBIoVkprqr9~1uqDYZ(wzF&n)m znjQ`$xlc$j0At3+*qjtp&ObFWv{I_Ekz3n3x<6(7zG%BIJaDa)B=XrHyKSAENgF?a@@9a*h#WMXYS*G z5jWSQ!H_r-J49#rpb43Cuyx{&6NJ}Z>mwLC(ohN3o^7<>)gX0Bb&k?TDc|TMHq1M} zV>znJDBd3Om;q(3R-+2+3XXXWug>$kH=2Am+;9xQ9eEaF~or|xY{|~)NG8F&- diff --git a/object/types.proto b/object/types.proto index 8f50f76..293f347 100644 --- a/object/types.proto +++ b/object/types.proto @@ -45,6 +45,8 @@ message Header { IntegrityHeader Integrity = 9; // StorageGroup contains meta information for the data audit storagegroup.StorageGroup StorageGroup = 10; + // PublicKey of owner of the object. Key is used for verification and can be based on NeoID or x509 cert. + PublicKey PublicKey = 11; } } @@ -122,3 +124,8 @@ message Object { // Payload is an object's payload bytes Payload = 3; } + +message PublicKey { + // Value contains marshaled ecdsa public key + bytes Value = 1; +} From c2f63107d0c20ad0c1edfa1745ba6b2d4b50f644 Mon Sep 17 00:00:00 2001 From: alexvanin Date: Thu, 16 Jan 2020 14:21:34 +0300 Subject: [PATCH 06/12] docs: Add doc about new public key header in object --- docs/object.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/object.md b/docs/object.md index e9248ba..7e86325 100644 --- a/docs/object.md +++ b/docs/object.md @@ -33,6 +33,7 @@ - [IntegrityHeader](#object.IntegrityHeader) - [Link](#object.Link) - [Object](#object.Object) + - [PublicKey](#object.PublicKey) - [Range](#object.Range) - [SystemHeader](#object.SystemHeader) - [Tombstone](#object.Tombstone) @@ -368,6 +369,7 @@ in distributed system. | PayloadChecksum | [bytes](#bytes) | | PayloadChecksum of actual object's payload | | Integrity | [IntegrityHeader](#object.IntegrityHeader) | | Integrity header with checksum of all above headers in the object | | StorageGroup | [storagegroup.StorageGroup](#storagegroup.StorageGroup) | | StorageGroup contains meta information for the data audit | +| PublicKey | [PublicKey](#object.PublicKey) | | PublicKey of owner of the object. Key is used for verification and can be based on NeoID or x509 cert. | @@ -407,6 +409,17 @@ in distributed system. | Payload | [bytes](#bytes) | | Payload is an object's payload | + + +### Message PublicKey + + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| Value | [bytes](#bytes) | | Value contains marshaled ecdsa public key | + + ### Message Range From f1418ef79dd7e998954a9f02ba9733f39124ed39 Mon Sep 17 00:00:00 2001 From: alexvanin Date: Thu, 16 Jan 2020 14:38:08 +0300 Subject: [PATCH 07/12] object: Add `CreateIntegrityHeader` function CreateIntegrityHeader function allow to optimize object put pipeline in neofs nodes. --- object/verification.go | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/object/verification.go b/object/verification.go index 761c04e..cbf12ab 100644 --- a/object/verification.go +++ b/object/verification.go @@ -63,6 +63,7 @@ func (m Object) verifySignature(key []byte, ih *IntegrityHeader) error { // Verify performs local integrity check by finding verification header and // integrity header. If header integrity is passed, function verifies // checksum of the object payload. +// todo: move this verification logic into separate library func (m Object) Verify() error { var ( err error @@ -111,22 +112,32 @@ func (m Object) Verify() error { return nil } -// Sign creates new integrity header and adds it to the end of the list of -// extended headers. -func (m *Object) Sign(key *ecdsa.PrivateKey) error { - headerChecksum, err := m.headersChecksum(false) +// CreateIntegrityHeader returns signed integrity header for the object +func CreateIntegrityHeader(obj *Object, key *ecdsa.PrivateKey) (*Header, error) { + headerChecksum, err := obj.headersChecksum(false) if err != nil { - return err + return nil, err } headerChecksumSignature, err := crypto.Sign(key, headerChecksum) if err != nil { - return err + return nil, err } - m.AddHeader(&Header{Value: &Header_Integrity{ + + return &Header{Value: &Header_Integrity{ Integrity: &IntegrityHeader{ HeadersChecksum: headerChecksum, ChecksumSignature: headerChecksumSignature, }, - }}) + }}, nil +} + +// Sign creates new integrity header and adds it to the end of the list of +// extended headers. +func (m *Object) Sign(key *ecdsa.PrivateKey) error { + ih, err := CreateIntegrityHeader(m, key) + if err != nil { + return err + } + m.AddHeader(ih) return nil } From 81cdfcc502a47ddc4f781903585f7ab264fa45f3 Mon Sep 17 00:00:00 2001 From: alexvanin Date: Thu, 16 Jan 2020 17:32:57 +0300 Subject: [PATCH 08/12] object: Update verify routine Verify routine now supports public key field to check if integrity header contains correct signature of object header. Verify also have strict check that integrity header is last header in the list of headers. --- object/extensions.go | 1 + object/verification.go | 28 +++++++++++++-------- object/verification_test.go | 50 ++++++++++++++++++++++++++++++++++--- 3 files changed, 64 insertions(+), 15 deletions(-) diff --git a/object/extensions.go b/object/extensions.go index 7427079..f6b10ab 100644 --- a/object/extensions.go +++ b/object/extensions.go @@ -1,4 +1,5 @@ package object +// todo: all extensions must be transferred to the separate util library import "github.com/nspcc-dev/neofs-proto/storagegroup" diff --git a/object/verification.go b/object/verification.go index cbf12ab..742375a 100644 --- a/object/verification.go +++ b/object/verification.go @@ -68,24 +68,30 @@ func (m Object) Verify() error { var ( err error checksum []byte + pubkey []byte ) - // Prepare structures - _, vh := m.LastHeader(HeaderType(VerifyHdr)) - if vh == nil { - return ErrHeaderNotFound - } - verify := vh.Value.(*Header_Verify).Verify - - _, ih := m.LastHeader(HeaderType(IntegrityHdr)) - if ih == nil { + ind, ih := m.LastHeader(HeaderType(IntegrityHdr)) + if ih == nil || ind != len(m.Headers) - 1{ return ErrHeaderNotFound } integrity := ih.Value.(*Header_Integrity).Integrity + // Prepare structures + _, vh := m.LastHeader(HeaderType(VerifyHdr)) + if vh == nil { + _, pkh := m.LastHeader(HeaderType(PublicKeyHdr)) + if pkh == nil { + return ErrHeaderNotFound + } + pubkey = pkh.Value.(*Header_PublicKey).PublicKey.Value + } else { + pubkey = vh.Value.(*Header_Verify).Verify.PublicKey + } + // Verify signature - err = m.verifySignature(verify.PublicKey, integrity) + err = m.verifySignature(pubkey, integrity) if err != nil { - return errors.Wrapf(err, "public key: %x", verify.PublicKey) + return errors.Wrapf(err, "public key: %x", pubkey) } // Verify checksum of header diff --git a/object/verification_test.go b/object/verification_test.go index f91e051..b538023 100644 --- a/object/verification_test.go +++ b/object/verification_test.go @@ -56,7 +56,7 @@ func TestObject_Verify(t *testing.T) { obj.SetPayload(payload) obj.SetHeader(&Header{Value: &Header_PayloadChecksum{[]byte("incorrect checksum")}}) - t.Run("error no integrity header", func(t *testing.T) { + t.Run("error no integrity header and pubkey", func(t *testing.T) { err = obj.Verify() require.EqualError(t, err, ErrHeaderNotFound.Error()) }) @@ -83,12 +83,25 @@ func TestObject_Verify(t *testing.T) { } obj.SetVerificationHeader(vh) + // validation header is not last + t.Run("error validation header is not last", func(t *testing.T) { + err = obj.Verify() + require.EqualError(t, err, ErrHeaderNotFound.Error()) + }) + + obj.Headers = obj.Headers[:len(obj.Headers)-2] + obj.SetVerificationHeader(vh) + obj.SetHeader(&Header{Value: &Header_Integrity{ih}}) + t.Run("error invalid header checksum", func(t *testing.T) { err = obj.Verify() require.EqualError(t, err, ErrVerifyHeader.Error()) }) - require.NoError(t, obj.Sign(sessionkey)) + obj.Headers = obj.Headers[:len(obj.Headers)-1] + genIH, err := CreateIntegrityHeader(obj, sessionkey) + require.NoError(t, err) + obj.SetHeader(genIH) t.Run("error invalid payload checksum", func(t *testing.T) { err = obj.Verify() @@ -96,10 +109,39 @@ func TestObject_Verify(t *testing.T) { }) obj.SetHeader(&Header{Value: &Header_PayloadChecksum{obj.PayloadChecksum()}}) - require.NoError(t, obj.Sign(sessionkey)) - t.Run("correct", func(t *testing.T) { + obj.Headers = obj.Headers[:len(obj.Headers)-1] + genIH, err = CreateIntegrityHeader(obj, sessionkey) + require.NoError(t, err) + obj.SetHeader(genIH) + + t.Run("correct with vh", func(t *testing.T) { err = obj.Verify() require.NoError(t, err) }) + + pkh := Header{Value: &Header_PublicKey{&PublicKey{ + Value: crypto.MarshalPublicKey(&key.PublicKey), + }}} + // replace vh with pkh + obj.Headers[len(obj.Headers)-2] = pkh + // re-sign object + obj.Sign(sessionkey) + + + t.Run("incorrect with bad public key", func(t *testing.T) { + err = obj.Verify() + require.Error(t, err) + }) + + obj.SetHeader(&Header{Value: &Header_PublicKey{&PublicKey{ + Value: dataPK, + }}}) + obj.Sign(sessionkey) + + t.Run("correct with good public key", func(t *testing.T) { + err = obj.Verify() + require.NoError(t, err) + }) + } From e88a6ee028d6c841f6e9a7789f9098c537dda440 Mon Sep 17 00:00:00 2001 From: alexvanin Date: Fri, 17 Jan 2020 12:37:04 +0300 Subject: [PATCH 09/12] session: Add owner's public key into session token We want to remove all innner ring queries to authenticate owner by public keys. Therefore we put public keys into session token. Later public keys could be gathered with NeoID or other centre of authority. --- session/types.pb.go | Bin 21404 -> 22862 bytes session/types.proto | 2 ++ 2 files changed, 2 insertions(+) diff --git a/session/types.pb.go b/session/types.pb.go index f597612920bb1e6cbb44068aed1b2e3650ff2995..5b2f5c4a1e079f2dc57e7c7804dfd064fe66a275 100644 GIT binary patch delta 2668 zcmZWr&u<$=6qel*x~^KGrl9bnblM{1sCKizcQ$H}im0N3sHoHflCi4U-PvL_v8~vs zj!?B6xp3M85^&+f4G{hdxN?BMf&=P_zW`>w&xxHThsk8-z4v|Zd+*KWho2gM{?_>Q z?uC~hj-Ke@y$|X~7j|!NZHZ65$o2;LNBVFg)MPTs2WqMd@pLf#T#TL$^+C&7u@J{U zy?*`5nT=Ov=Rl7;L$$AWmS*+sGaHRbeevwK^R0{DpRKpAoxilJr%QwOrZE2hp1aXn zp4Gpc+nE1x=}My+$@-u5NtG8J;m$&BR~^_ja62u>oq3`CLq>K@GrN{JNfH?4ILB=q z+r7qZk=lKTy^C<6vL^}=6kwze02oy>4^}SxB1DQ2JCZArJiGU}0#m_0hmCUWt&i9R zPW%W6gd_PBG`!N91|TEtiNS{e5n>d$mS7(uPrZViAw-N@nF4_%BOLjF&OqM99tg7( z2`Z$f07jC9-B+^`WXOX1l*Pz^5W~9!y%6*~rVC=kj6qexEdqYd6tEI4fqm{nDo7|3 z15la5fs==u5;3S!2*%7Ur?}u!06)iV3A6&SjU-0f1ep`xBxO5E9l@Dv&HjK}V$OHX zHDrwtBZ4Wp#;g_4T-+v90Zhp^P(%po|6Y5&GVxui36l^gArM`r2cdEVQwYz#3?NjJ zGZ;{q2OHT#t`cj(6@e507LBJmz=v}H5nSw1=0)#Di>{$+P*c(rc?YD8dhlG4Dw5(j zv3EHl>6}Z1JehM9I<2AaI`c8;8q z?GvM*8T?pczMd=q%VWmVMCIFNB(Vt09K6f}V@E4RxC|F@1rPQzUlKcEM{lnNCI{RH zmlUgyN-{&X5>Je_79m531XRs{9ES_3Dj-?UtU_D4I7;~RfGgRvV=}V9YS1hK-!R5@ z;lM{CCwaaO*fU$cVH)_9Eup9tjwH1`qGu6u9Oaxk5`$u#w+P}Uv;jUJ4)!F;bEOuX z10R+ddzAz#mNkZ~CB;Qle&RT3oR6H1Mpe0@(b%i}=q!*uiUjfrXp@G-NdRH^9IW%B zSVD~w0tEH*H{ZBoipCZ(A*~+#E;5Wizy8+WFKrJ>v8RXa{aed_6*k3t!WCb(9H$%| zh{65h?o4d&oHDDwyCJR)MECSf4?g|PmQz1?d;Rh<^2)`J@3xZ{fsd{?ji=)bx?TIL zxHG-e8}!AFNhb8o$+LO$`e)9EFFK!O{iq`{OZq?!A8WCi9TIc)OgtMQvm_fg-)TC} z>c85b&VRo7&DFJBO|+2pwXJ?*GXMSkX0!gvJ6}zViyDvhusESsN9?O7y4~w%hf`Cf z@n|x=H!Sq53lW$~J{ljMaO$06-}U+(!CbB2+sARNj7E(6^R?)CV}AMLuh;$uafHLQ delta 2045 zcmZXVy^0h;6opw~!4*~m1#w~61vd~}r24PAIxg-@?#G5Ul!6ivvzjQ*-OybM8HLZ_SUZgU??MzCArYIs5PP^259F{qrYh+ZV^r zcK2_dAMU>1-W*(O+wJ!|AD1>=oSC@|WsOZ)8*_2v$jp_))R%Q&9mld)z=&&Wip358 ze0*K@iPZr;u-3lV1DKVCU~02znaA=q$F8g`s2)5E#=t(Oluu<3!p1X@S7Sk-gaFUv zU>F1eL5))f&BUHUmRUcBs$ldSkl0)+S88_HlYpk;S=TT~w*YkywlqvwCX$?D377zi zl(X7PcFWv@H>yIisM)t-==c$dwjecNNL)!D@EIixNh&W#)PN+0>>3b8ENz!dSj^lh z0$*KR5+``dK5~h|>(v-US?nHcrzRo04j)?>vR2S_)TUKp_+0se+;3>*ghyN}>EUk( z_ICUG?!Bd;b+}h5mU86ou(XsRHPx>@DOSJ)PCGmku{B9|TvU}vw@?WQ&ybPXK^sk?eoTCW~?DzyPV+G_|R1csW|hZ##+sCI-i zKdVJ0uWJHnWuV6$c1?pNK|o53gd5Da@o zYj7;$DpmE~{(GvwKK;cd$w}Y7Q7h?jcYmuY41p#Z@fwj;lGI4AX*BFB*7ffY=`|B( sd%8K Date: Fri, 17 Jan 2020 12:38:34 +0300 Subject: [PATCH 10/12] docs: Add documentation on public keys field in session token --- docs/session.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/session.md b/docs/session.md index e8633d3..ba615c3 100644 --- a/docs/session.md +++ b/docs/session.md @@ -115,6 +115,7 @@ User token granting rights for object manipulation | 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 | From b556d54f16acd1de144379329a49c1c1e1570623 Mon Sep 17 00:00:00 2001 From: alexvanin Date: Fri, 17 Jan 2020 12:39:00 +0300 Subject: [PATCH 11/12] session: Modify verify routine to check owner id connection with public keys --- session/store_test.go | 6 ++++-- session/types.go | 23 +++++++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/session/store_test.go b/session/store_test.go index 1a9e977..66f99d4 100644 --- a/session/store_test.go +++ b/session/store_test.go @@ -31,20 +31,22 @@ func newTestClient(t *testing.T) *testClient { 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 - require.False(t, token.Verify(&c.PublicKey)) + 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(&c.PublicKey)) + require.True(t, token.Verify(keys...)) } func TestTokenStore(t *testing.T) { diff --git a/session/types.go b/session/types.go index aff7cca..08abec8 100644 --- a/session/types.go +++ b/session/types.go @@ -6,6 +6,7 @@ import ( "sync" crypto "github.com/nspcc-dev/neofs-crypto" + "github.com/nspcc-dev/neofs-proto/chain" "github.com/nspcc-dev/neofs-proto/internal" "github.com/nspcc-dev/neofs-proto/refs" "github.com/pkg/errors" @@ -111,11 +112,24 @@ func (m *Token) Sign(key *ecdsa.PrivateKey) error { 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 @@ -156,3 +170,12 @@ func (m *VerificationHeader) Verify(keys ...*ecdsa.PublicKey) bool { } 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 +} From 34828f557828466f15e1dc803db0a70e182c85fb Mon Sep 17 00:00:00 2001 From: alexvanin Date: Fri, 17 Jan 2020 14:06:08 +0300 Subject: [PATCH 12/12] Update changelog for v0.2.9 --- CHANGELOG.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b76c77e..dc0bb81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,23 @@ # Changelog This is the changelog for NeoFS Proto +## [0.2.9] - 2020-01-17 + +### Added +- Docs for container ACL field +- Public key header in the object with docs +- Public key field in the session token with docs + +### Changed +- Routine to verify correct object checks if integrity header is last and +may use public key header if verification header is not present +- Routine to verify correct session token checks if keys in the token +associated with owner id +- Updated neofs-crypto to v0.2.3 + +### Removed +- Timestamp in object tombstone header + ## [0.2.8] - 2019-12-21 ### Added @@ -88,3 +105,4 @@ Initial public release [0.2.6]: https://github.com/nspcc-dev/neofs-proto/compare/v0.2.5...v0.2.6 [0.2.7]: https://github.com/nspcc-dev/neofs-proto/compare/v0.2.6...v0.2.7 [0.2.8]: https://github.com/nspcc-dev/neofs-proto/compare/v0.2.7...v0.2.8 +[0.2.9]: https://github.com/nspcc-dev/neofs-proto/compare/v0.2.8...v0.2.9