22package namer
33
44import (
5+ "bytes"
6+ "errors"
7+ "fmt"
8+ "strings"
9+
10+ "github.com/tarantool/go-storage/crypto"
11+ "github.com/tarantool/go-storage/hasher"
512 "github.com/tarantool/go-storage/kv"
13+ "github.com/tarantool/go-storage/marshaller"
614)
715
816// KeyType represents key types.
@@ -17,6 +25,19 @@ const (
1725 KeyTypeSignature
1826)
1927
28+ const (
29+ hashName = "hash"
30+ sigName = "sig"
31+ namesNumber = 3
32+ )
33+
34+ var (
35+ // ErrInvalidKey is returned when missing key, hash or signature.
36+ ErrInvalidKey = errors .New ("missing key, hash or signature" )
37+ // ErrHashMismatch is returned when hash mismatch.
38+ ErrHashMismatch = errors .New ("hash mismatch" )
39+ )
40+
2041// Key implements internal realization.
2142type Key struct {
2243 Name string // Object identificator.
@@ -30,6 +51,65 @@ type Namer interface {
3051 ParseNames (names []string ) []Key // Convert names into keys.
3152}
3253
54+ // DefaultNamer represents default namer.
55+ type DefaultNamer struct {
56+ prefix string
57+ }
58+
59+ // NewDefaultNamer returns new DefaultNamer object.
60+ func NewDefaultNamer (prefix string ) * DefaultNamer {
61+ return & DefaultNamer {
62+ prefix : prefix ,
63+ }
64+ }
65+
66+ // GenerateNames generates set of names from basic name.
67+ func (n * DefaultNamer ) GenerateNames (name string ) []string {
68+ return []string {
69+ n .prefix + "/" + name ,
70+ n .prefix + "/" + hashName + "/" + name ,
71+ n .prefix + "/" + sigName + "/" + name ,
72+ }
73+ }
74+
75+ // ParseNames returns set of Keys with different types.
76+ func (n * DefaultNamer ) ParseNames (names []string ) []Key {
77+ keys := make ([]Key , 0 , namesNumber )
78+
79+ for _ , name := range names {
80+ var key Key
81+
82+ // Remove prefix.
83+ result := strings .ReplaceAll (name , n .prefix , "" )
84+
85+ parts := strings .Split (result , "/" )
86+
87+ key .Name = name
88+
89+ switch parts [1 ] {
90+ case "hash" :
91+ {
92+ key .Property = ""
93+ key .Type = KeyTypeHash
94+ }
95+ case "sig" :
96+ {
97+ key .Property = ""
98+ key .Type = KeyTypeSignature
99+ }
100+ default :
101+ {
102+ key .Property = ""
103+ key .Type = KeyTypeValue
104+ }
105+ }
106+
107+ keys = append (keys , key )
108+ }
109+
110+ return keys
111+ }
112+
33113// Generator generates signer K/V pairs.
34114// Implementation should use `generic` and will used for strong typing of the solution.
35115type Generator [T any ] interface {
@@ -40,3 +120,121 @@ type Generator[T any] interface {
40120type Validator [T any ] interface {
41121 Validate (pairs []kv.KeyValue ) (T , error )
42122}
123+
124+ // DefaultGeneratorValidator represent default generator-validator.
125+ type DefaultGeneratorValidator [T any ] struct {
126+ Namer Namer
127+ Hasher hasher.Hasher
128+ SignerVerifier crypto.SignerVerifier
129+ Marshaller marshaller.Marshallable
130+ }
131+
132+ // NewDefaultGeneratorValidator returns new object.
133+ func NewDefaultGeneratorValidator [T any ](
134+ namer Namer ,
135+ hasher hasher.Hasher ,
136+ signverifier crypto.SignerVerifier ,
137+ marshaller marshaller.Marshallable ,
138+ ) DefaultGeneratorValidator [T ] {
139+ return DefaultGeneratorValidator [T ]{
140+ Namer : namer ,
141+ Hasher : hasher ,
142+ SignerVerifier : signverifier ,
143+ Marshaller : marshaller ,
144+ }
145+ }
146+
147+ // Generate create KV pairs with value, hash and signature.
148+ func (gv DefaultGeneratorValidator [T ]) Generate (name string , value T ) ([]kv.KeyValue , error ) {
149+ var kvList []kv.KeyValue
150+
151+ blob , err := gv .Marshaller .Marshal (value )
152+ if err != nil {
153+ return nil , fmt .Errorf ("failed to marshal: %w" , err )
154+ }
155+
156+ hash , err := gv .Hasher .Hash (blob )
157+ if err != nil {
158+ return nil , fmt .Errorf ("failed to hash: %w" , err )
159+ }
160+
161+ signature , err := gv .SignerVerifier .Sign (hash )
162+ if err != nil {
163+ return nil , fmt .Errorf ("failed to sign: %w" , err )
164+ }
165+
166+ names := gv .Namer .GenerateNames (name )
167+ keys := gv .Namer .ParseNames (names )
168+
169+ for _ , key := range keys {
170+ switch key .Type {
171+ case KeyTypeValue :
172+ {
173+ kvList = append (kvList , kv.KeyValue {
174+ Key : []byte (key .Name ),
175+ Value : blob ,
176+ ModRevision : 1 ,
177+ })
178+ }
179+ case KeyTypeHash :
180+ {
181+ kvList = append (kvList , kv.KeyValue {
182+ Key : []byte (key .Name ),
183+ Value : hash ,
184+ ModRevision : 1 ,
185+ })
186+ }
187+ case KeyTypeSignature :
188+ {
189+ kvList = append (kvList , kv.KeyValue {
190+ Key : []byte (key .Name ),
191+ Value : signature ,
192+ ModRevision : 1 ,
193+ })
194+ }
195+ }
196+ }
197+
198+ return kvList , nil
199+ }
200+
201+ // Validate checks hash match, verify signature, unmarshall object and return it.
202+ func (gv DefaultGeneratorValidator [T ]) Validate (pairs []kv.KeyValue ) (T , error ) {
203+ var value T
204+
205+ var blob []byte
206+
207+ var hash , signature []byte
208+
209+ for _ , keyvalue := range pairs {
210+ switch {
211+ case strings .Contains (string (keyvalue .Key ), hashName ):
212+ hash = keyvalue .Value
213+ case strings .Contains (string (keyvalue .Key ), sigName ):
214+ signature = keyvalue .Value
215+ default :
216+ blob = keyvalue .Value
217+ }
218+ }
219+
220+ if blob == nil || hash == nil || signature == nil {
221+ return value , ErrInvalidKey
222+ }
223+
224+ err := gv .SignerVerifier .Verify (hash , signature )
225+ if err != nil {
226+ return value , fmt .Errorf ("signature verification failed: %w" , err )
227+ }
228+
229+ computedHash , err := gv .Hasher .Hash (blob )
230+ if ! bytes .Equal (computedHash , hash ) || err != nil {
231+ return value , ErrHashMismatch
232+ }
233+
234+ err = gv .Marshaller .Unmarshal (blob , & value )
235+ if err != nil {
236+ return value , fmt .Errorf ("failed to unmarshal: %w" , err )
237+ }
238+
239+ return value , nil
240+ }
0 commit comments