-
Notifications
You must be signed in to change notification settings - Fork 14
/
target.go
200 lines (160 loc) · 4.42 KB
/
target.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
package eacl
import (
"bytes"
"crypto/ecdsa"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
v2acl "github.com/nspcc-dev/neofs-api-go/v2/acl"
)
// Target is a group of request senders to match ContainerEACL. Defined by role enum
// and set of public keys.
//
// Target is compatible with v2 acl.EACLRecord.Target message.
type Target struct {
role Role
keys [][]byte
}
func ecdsaKeysToPtrs(keys []ecdsa.PublicKey) []*ecdsa.PublicKey {
keysPtr := make([]*ecdsa.PublicKey, len(keys))
for i := range keys {
keysPtr[i] = &keys[i]
}
return keysPtr
}
// CopyTo writes deep copy of the [Target] to dst.
func (t Target) CopyTo(dst *Target) {
dst.role = t.role
dst.keys = make([][]byte, len(t.keys))
for i, k := range t.keys {
dst.keys[i] = make([]byte, len(k))
copy(dst.keys[i], t.keys[i])
}
}
// BinaryKeys returns list of public keys to identify
// target subject in a binary format.
//
// Each element of the resulting slice is a serialized compressed public key. See [elliptic.MarshalCompressed].
// Use [neofsecdsa.PublicKey.Decode] to decode it into a type-specific structure.
//
// The value returned shares memory with the structure itself, so changing it can lead to data corruption.
// Make a copy if you need to change it.
func (t *Target) BinaryKeys() [][]byte {
return t.keys
}
// SetBinaryKeys sets list of binary public keys to identify
// target subject.
//
// Each element of the keys parameter is a slice of bytes is a serialized compressed public key.
// See [elliptic.MarshalCompressed].
func (t *Target) SetBinaryKeys(keys [][]byte) {
t.keys = keys
}
// SetTargetECDSAKeys converts ECDSA public keys to a binary
// format and stores them in Target.
func SetTargetECDSAKeys(t *Target, pubs ...*ecdsa.PublicKey) {
binKeys := t.BinaryKeys()
ln := len(pubs)
if cap(binKeys) >= ln {
binKeys = binKeys[:0]
} else {
binKeys = make([][]byte, 0, ln)
}
for i := 0; i < ln; i++ {
binKeys = append(binKeys, (*keys.PublicKey)(pubs[i]).Bytes())
}
t.SetBinaryKeys(binKeys)
}
// TargetECDSAKeys interprets binary public keys of Target
// as ECDSA public keys. If any key has a different format,
// the corresponding element will be nil.
func TargetECDSAKeys(t *Target) []*ecdsa.PublicKey {
binKeys := t.BinaryKeys()
ln := len(binKeys)
pubs := make([]*ecdsa.PublicKey, ln)
for i := 0; i < ln; i++ {
p := new(keys.PublicKey)
if p.DecodeBytes(binKeys[i]) == nil {
pubs[i] = (*ecdsa.PublicKey)(p)
}
}
return pubs
}
// SetRole sets target subject's role class.
func (t *Target) SetRole(r Role) {
t.role = r
}
// Role returns target subject's role class.
func (t Target) Role() Role {
return t.role
}
// ToV2 converts Target to v2 acl.EACLRecord.Target message.
//
// Nil Target converts to nil.
func (t *Target) ToV2() *v2acl.Target {
if t == nil {
return nil
}
target := new(v2acl.Target)
target.SetRole(t.role.ToV2())
target.SetKeys(t.keys)
return target
}
// NewTarget creates, initializes and returns blank Target instance.
//
// Defaults:
// - role: RoleUnknown;
// - keys: nil.
func NewTarget() *Target {
return NewTargetFromV2(new(v2acl.Target))
}
// NewTargetFromV2 converts v2 acl.EACLRecord.Target message to Target.
func NewTargetFromV2(target *v2acl.Target) *Target {
if target == nil {
return new(Target)
}
return &Target{
role: RoleFromV2(target.GetRole()),
keys: target.GetKeys(),
}
}
// Marshal marshals Target into a protobuf binary form.
func (t *Target) Marshal() ([]byte, error) {
return t.ToV2().StableMarshal(nil), nil
}
// Unmarshal unmarshals protobuf binary representation of Target.
func (t *Target) Unmarshal(data []byte) error {
fV2 := new(v2acl.Target)
if err := fV2.Unmarshal(data); err != nil {
return err
}
*t = *NewTargetFromV2(fV2)
return nil
}
// MarshalJSON encodes Target to protobuf JSON format.
func (t *Target) MarshalJSON() ([]byte, error) {
return t.ToV2().MarshalJSON()
}
// UnmarshalJSON decodes Target from protobuf JSON format.
func (t *Target) UnmarshalJSON(data []byte) error {
tV2 := new(v2acl.Target)
if err := tV2.UnmarshalJSON(data); err != nil {
return err
}
*t = *NewTargetFromV2(tV2)
return nil
}
// equalTargets compares Target with each other.
func equalTargets(t1, t2 Target) bool {
if t1.Role() != t2.Role() {
return false
}
keys1, keys2 := t1.BinaryKeys(), t2.BinaryKeys()
if len(keys1) != len(keys2) {
return false
}
for i := 0; i < len(keys1); i++ {
if !bytes.Equal(keys1[i], keys2[i]) {
return false
}
}
return true
}