@@ -12,39 +12,71 @@ import (
1212
1313 "github.com/theupdateframework/go-tuf/data"
1414 "github.com/theupdateframework/go-tuf/encrypted"
15+ "github.com/theupdateframework/go-tuf/internal/sets"
1516 "github.com/theupdateframework/go-tuf/pkg/keys"
1617 "github.com/theupdateframework/go-tuf/util"
1718)
1819
19- func signers (privateKeys []* data.PrivateKey ) []keys.Signer {
20- res := make ([]keys.Signer , 0 , len (privateKeys ))
21- for _ , k := range privateKeys {
22- signer , err := keys .GetSigner (k )
23- if err != nil {
24- continue
25- }
26- res = append (res , signer )
27- }
28- return res
20+ type LocalStore interface {
21+ // GetMeta returns a map from metadata file names (e.g. root.json) to their raw JSON payload or an error.
22+ GetMeta () (map [string ]json.RawMessage , error )
23+
24+ // SetMeta is used to update a metadata file name with a JSON payload.
25+ SetMeta (name string , meta json.RawMessage ) error
26+
27+ // WalkStagedTargets calls targetsFn for each staged target file in paths.
28+ // If paths is empty, all staged target files will be walked.
29+ WalkStagedTargets (paths []string , targetsFn TargetsWalkFunc ) error
30+
31+ // FileIsStaged determines if a metadata file is currently staged, to avoid incrementing
32+ // version numbers repeatedly while staged.
33+ FileIsStaged (filename string ) bool
34+
35+ // Commit is used to publish staged files to the repository
36+ //
37+ // This will also reset the staged meta to signal incrementing version numbers.
38+ // TUF 1.0 requires that the root metadata version numbers in the repository does not
39+ // gaps. To avoid this, we will only increment the number once until we commit.
40+ Commit (bool , map [string ]int , map [string ]data.Hashes ) error
41+
42+ // GetSigners return a list of signers for a role.
43+ GetSigners (role string ) ([]keys.Signer , error )
44+
45+ // SaveSigner adds a signer to a role.
46+ SaveSigner (role string , signer keys.Signer ) error
47+
48+ // SignersForRole return a list of signing keys for a role.
49+ SignersForKeyIDs (keyIDs []string ) []keys.Signer
50+
51+ // Clean is used to remove all staged manifests.
52+ Clean () error
53+ }
54+
55+ type PassphraseChanger interface {
56+ // ChangePassphrase changes the passphrase for a role keys file.
57+ ChangePassphrase (string ) error
2958}
3059
3160func MemoryStore (meta map [string ]json.RawMessage , files map [string ][]byte ) LocalStore {
3261 if meta == nil {
3362 meta = make (map [string ]json.RawMessage )
3463 }
3564 return & memoryStore {
36- meta : meta ,
37- stagedMeta : make (map [string ]json.RawMessage ),
38- files : files ,
39- signers : make (map [string ][]keys.Signer ),
65+ meta : meta ,
66+ stagedMeta : make (map [string ]json.RawMessage ),
67+ files : files ,
68+ signerForKeyID : make (map [string ]keys.Signer ),
69+ keyIDsForRole : make (map [string ][]string ),
4070 }
4171}
4272
4373type memoryStore struct {
4474 meta map [string ]json.RawMessage
4575 stagedMeta map [string ]json.RawMessage
4676 files map [string ][]byte
47- signers map [string ][]keys.Signer
77+
78+ signerForKeyID map [string ]keys.Signer
79+ keyIDsForRole map [string ][]string
4880}
4981
5082func (m * memoryStore ) GetMeta () (map [string ]json.RawMessage , error ) {
@@ -105,14 +137,53 @@ func (m *memoryStore) Commit(consistentSnapshot bool, versions map[string]int, h
105137}
106138
107139func (m * memoryStore ) GetSigners (role string ) ([]keys.Signer , error ) {
108- return m .signers [role ], nil
140+ keyIDs , ok := m .keyIDsForRole [role ]
141+ if ok {
142+ return m .SignersForKeyIDs (keyIDs ), nil
143+ }
144+
145+ return nil , nil
109146}
110147
111148func (m * memoryStore ) SaveSigner (role string , signer keys.Signer ) error {
112- m .signers [role ] = append (m .signers [role ], signer )
149+ keyIDs := signer .PublicData ().IDs ()
150+
151+ for _ , keyID := range keyIDs {
152+ m .signerForKeyID [keyID ] = signer
153+ }
154+
155+ mergedKeyIDs := sets .DeduplicateStrings (append (m .keyIDsForRole [role ], keyIDs ... ))
156+ m .keyIDsForRole [role ] = mergedKeyIDs
113157 return nil
114158}
115159
160+ func (m * memoryStore ) SignersForKeyIDs (keyIDs []string ) []keys.Signer {
161+ signers := []keys.Signer {}
162+ keyIDsSeen := map [string ]struct {}{}
163+
164+ for _ , keyID := range keyIDs {
165+ signer , ok := m .signerForKeyID [keyID ]
166+ if ! ok {
167+ continue
168+ }
169+ addSigner := false
170+
171+ for _ , skid := range signer .PublicData ().IDs () {
172+ if _ , seen := keyIDsSeen [skid ]; ! seen {
173+ addSigner = true
174+ }
175+
176+ keyIDsSeen [skid ] = struct {}{}
177+ }
178+
179+ if addSigner {
180+ signers = append (signers , signer )
181+ }
182+ }
183+
184+ return signers
185+ }
186+
116187func (m * memoryStore ) Clean () error {
117188 return nil
118189}
@@ -126,16 +197,17 @@ func FileSystemStore(dir string, p util.PassphraseFunc) LocalStore {
126197 return & fileSystemStore {
127198 dir : dir ,
128199 passphraseFunc : p ,
129- signers : make (map [string ][]keys.Signer ),
200+ signerForKeyID : make (map [string ]keys.Signer ),
201+ keyIDsForRole : make (map [string ][]string ),
130202 }
131203}
132204
133205type fileSystemStore struct {
134206 dir string
135207 passphraseFunc util.PassphraseFunc
136208
137- // signers is a cache of persisted keys to avoid decrypting multiple times
138- signers map [string ][]keys. Signer
209+ signerForKeyID map [ string ] keys. Signer
210+ keyIDsForRole map [string ][]string
139211}
140212
141213func (f * fileSystemStore ) repoDir () string {
@@ -333,18 +405,63 @@ func (f *fileSystemStore) Commit(consistentSnapshot bool, versions map[string]in
333405}
334406
335407func (f * fileSystemStore ) GetSigners (role string ) ([]keys.Signer , error ) {
336- if keys , ok := f .signers [role ]; ok {
337- return keys , nil
408+ keyIDs , ok := f .keyIDsForRole [role ]
409+ if ok {
410+ return f .SignersForKeyIDs (keyIDs ), nil
338411 }
339- keys , _ , err := f .loadPrivateKeys (role )
412+
413+ privKeys , _ , err := f .loadPrivateKeys (role )
340414 if err != nil {
341415 if os .IsNotExist (err ) {
342416 return nil , nil
343417 }
344418 return nil , err
345419 }
346- f .signers [role ] = signers (keys )
347- return f .signers [role ], nil
420+
421+ signers := []keys.Signer {}
422+ for _ , key := range privKeys {
423+ signer , err := keys .GetSigner (key )
424+ if err != nil {
425+ return nil , err
426+ }
427+
428+ // Cache the signers.
429+ for _ , keyID := range signer .PublicData ().IDs () {
430+ f .keyIDsForRole [role ] = append (f .keyIDsForRole [role ], keyID )
431+ f .signerForKeyID [keyID ] = signer
432+ }
433+ signers = append (signers , signer )
434+ }
435+
436+ return signers , nil
437+ }
438+
439+ func (f * fileSystemStore ) SignersForKeyIDs (keyIDs []string ) []keys.Signer {
440+ signers := []keys.Signer {}
441+ keyIDsSeen := map [string ]struct {}{}
442+
443+ for _ , keyID := range keyIDs {
444+ signer , ok := f .signerForKeyID [keyID ]
445+ if ! ok {
446+ continue
447+ }
448+
449+ addSigner := false
450+
451+ for _ , skid := range signer .PublicData ().IDs () {
452+ if _ , seen := keyIDsSeen [skid ]; ! seen {
453+ addSigner = true
454+ }
455+
456+ keyIDsSeen [skid ] = struct {}{}
457+ }
458+
459+ if addSigner {
460+ signers = append (signers , signer )
461+ }
462+ }
463+
464+ return signers
348465}
349466
350467// ChangePassphrase changes the passphrase for a role keys file. Implements
@@ -391,15 +508,15 @@ func (f *fileSystemStore) SaveSigner(role string, signer keys.Signer) error {
391508 }
392509
393510 // add the key to the existing keys (if any)
394- keys , pass , err := f .loadPrivateKeys (role )
511+ privKeys , pass , err := f .loadPrivateKeys (role )
395512 if err != nil && ! os .IsNotExist (err ) {
396513 return err
397514 }
398515 key , err := signer .MarshalPrivateKey ()
399516 if err != nil {
400517 return err
401518 }
402- keys = append (keys , key )
519+ privKeys = append (privKeys , key )
403520
404521 // if loadPrivateKeys didn't return a passphrase (because no keys yet exist)
405522 // and passphraseFunc is set, get the passphrase so the keys file can
@@ -414,13 +531,13 @@ func (f *fileSystemStore) SaveSigner(role string, signer keys.Signer) error {
414531
415532 pk := & persistedKeys {}
416533 if pass != nil {
417- pk .Data , err = encrypted .Marshal (keys , pass )
534+ pk .Data , err = encrypted .Marshal (privKeys , pass )
418535 if err != nil {
419536 return err
420537 }
421538 pk .Encrypted = true
422539 } else {
423- pk .Data , err = json .MarshalIndent (keys , "" , "\t " )
540+ pk .Data , err = json .MarshalIndent (privKeys , "" , "\t " )
424541 if err != nil {
425542 return err
426543 }
@@ -432,7 +549,27 @@ func (f *fileSystemStore) SaveSigner(role string, signer keys.Signer) error {
432549 if err := util .AtomicallyWriteFile (f .keysPath (role ), append (data , '\n' ), 0600 ); err != nil {
433550 return err
434551 }
435- f .signers [role ] = append (f .signers [role ], signer )
552+
553+ // Merge privKeys into f.keyIDsForRole and register signers with
554+ // f.signerForKeyID.
555+ keyIDsForRole := f .keyIDsForRole [role ]
556+ for _ , key := range privKeys {
557+ signer , err := keys .GetSigner (key )
558+ if err != nil {
559+ return err
560+ }
561+
562+ keyIDs := signer .PublicData ().IDs ()
563+
564+ for _ , keyID := range keyIDs {
565+ f .signerForKeyID [keyID ] = signer
566+ }
567+
568+ keyIDsForRole = append (keyIDsForRole , keyIDs ... )
569+ }
570+
571+ f .keyIDsForRole [role ] = sets .DeduplicateStrings (keyIDsForRole )
572+
436573 return nil
437574}
438575
0 commit comments