@@ -48,8 +48,8 @@ after a rotation to null. The client will detect a rotation
4848to a null key and treat it as if the metadata was unsigned.
4949
5050A delegator to a role A is able to help A recover from a rotation to null of A by
51- delegating to a new set of keys for A.
52- Additionally, a delegator can overrule a rotate file by delegating to the role
51+ delegating to a new set of keys for A with a new role name .
52+ Additionally, a delegator can overrule a rotate file by delegating to a new role
5353with a new set of keys. This ensures that the delegator is still the source of
5454trust, but allows the role to act independently.
5555
@@ -144,10 +144,10 @@ mechanism to be used by other delegations, and extends it with self-revocation.
144144# Specification
145145
146146To support key rotation, the new metadata type ` rotate ` is
147- introduced, which contains the new public key(s), the threshold, a hash
148- of the previous rotate file in the chain , and is
149- signed by a threshold of old public keys. The intuition is while
150- delegations keep intact, the targets can rotate keys, shrink or grow .
147+ introduced, which contains the new public key(s), the threshold, a version
148+ number , and is
149+ signed by a threshold of old public keys. The intuition is that while
150+ delegations stay intact, the targets can rotate keys, remove keys, or add keys .
151151
152152## Rotate file
153153
@@ -156,8 +156,8 @@ signatures wrapper as in tuf spec, not shown here):
156156
157157``` python
158158{
159- " _type" : " rotate" ,
160- " previous " : PREV_FILENAME
159+ " _type" : " rotate" ,
160+ " version " : VERSION ,
161161 " role" : ROLE ,
162162 " keys" : {
163163 KEYID : KEY
@@ -168,60 +168,81 @@ signatures wrapper as in tuf spec, not shown here):
168168
169169Where ROLE, KEYID, KEY, and THRESHOLD are as defined in the original
170170tuf spec. The value of ROLE has to be the same as the role for the
171- delegation. The value of THRESHOLD is its new value. PREV_FILENAME is
172- the name of the previous rotate file in the chain, or the empty string if this is
173- the first rotate file for this role. The keys specify the new valid keys
171+ delegation. The value of THRESHOLD is its new value. VERSION is
172+ the integer version number of rotate files for this role. Version
173+ numbers MUST increase by exactly 1 from the previous rotate file for
174+ this role. The keys specify the new valid keys
174175and associated key ids (which may be a subset or superset of
175- the old ones). A rotate file does _ not_ contain an expiration date,
176+ the old ones). A rotate file does _ not_ contain an expiration date, as
176177it is meant to be signed once and never modified. The rotate
177- file has to be signed with an old threshold of old keys.
178+ file has to be signed with an old threshold of old keys. All keys in a
179+ rotation chain, other than a chain that has a rotation to null, should
180+ be securely stored.
178181
179- The rotate file will go into a repository in a 'rotate' folder that contains
182+ The rotate file will go into a 'rotate' folder on the repository that contains
180183all rotate files for the repository. These files will be listed in snapshot
181- metadata for the repository so that the client can verify that they recieve
182- all current rotate files.
184+ metadata for the repository so that the client can verify that they receive
185+ all current rotate files. The files listed in snapshot SHOULD contain a
186+ hash in order to ensure that an attacker that later compromises previously
187+ trusted keys cannot replace a rotate file. If a rotate file listed in
188+ snapshot for a role is not found, the user MUST act as if the role's metadata
189+ is not signed with a valid threshold of keys.
183190
184191Let's consider a motivating example, project foo is delegated to Alice.
185192Alice's computer with the key material got stolen, but the disk was
186193encrypted. To be safe, she decides to get her key from her backup and
187- roll over her key to a fresh one. To do that, she creates a file
188- ` foo.rotate.ID.PREV ` . This file contains her new key, a threshold of 1, and
194+ rotate her key to a fresh one. To do that, she creates a file
195+ ` foo.rotate.VERSION ` . This file contains her new key, a threshold of 1, and
189196is signed with her old key. She signs her targets file with the new key,
190197and uploads both the rotate file and the freshly signed targets file to
191198the repository.
192199
193- The first filename suffix, referred as ` ID ` above and below, is the hex
194- representation of the SHA256 hash of the concatenation (using "." as
195- separator) of the KEYIDs (in ascending lexical order), and the old
196- threshold value, encoded decimal as ASCII (0x31 for 1, 0x32 for 2,
197- 0x31 0x30 for 10).
198-
199- The second suffix, referred to as 'PREV' is a SHA256 hash of the previous
200- rotate file, or the empty string if there is no previous rotate file.
201- This prevents rotation cycles.
200+ The filename suffix, referred as ` VERSION ` above and below, is the
201+ same as the VERSION listed in the metadata.
202202
203203The existing delegation to Alice's old key is still valid. The client will
204- start with this delegation and look for rotation files to determine the current
205- set of trusted keys.
204+ start with this delegation and look for rotate files to determine the current
205+ set of trusted keys. They will see ` foo.rotate.1 ` and discover Alice's new key.
206206
207- If the delegation is changed to include her new key, it will also be valid. Any
208- old rotate files for this role should be deleted and removed from snapshot on
209- the next snapshot key rotation. The client will determine the correct rotate file
210- to begin the chain using the set of keys in the delegation for the role as the ` ID ` .
207+ If the delegation is changed to Alice's new key, it should use a new role name to
208+ over-rule any existing rotate files. Any
209+ old rotate files for the old role should be deleted and removed from snapshot on
210+ the next snapshot key rotation. The client will determine the correct rotate file for the new role
211+ by starting from VERSION 1.
211212
212213## Client workflow
213214
214- A client who wants to install foo now fetches Alice's targets file, and
215- during verification looks for a file named ` foo.rotate.ID.PREV ` in the
216- rotate folder, ID and PREV are explained above using Alice's old keyid.
217- The client sees the file, fetches
218- it and verifies this rotate file using the public key from the delegation.
219- The client then looks for a rotate file with the new keyid, repeating until
220- there is no matching rotate file to ensure up to date key information. This
221- establishes trust in Alice's new key, and the client can now verify the
222- signature of Alice's targets file using the new key. If key data is missing
223- or there is a rotation to null the targets file is invalid and the client will
224- proceed with the update process as if verification for this file failed.
215+ A client who wants to install foo now fetches Alice's targets file and will
216+ determine the set of trusted keys for this role as follows. The client will start
217+ with the keys listed in the delegation as trusted keys for this role.
218+ The client will then look for all files that begin with ` rotate/foo.rotate ` in
219+ the snapshot metadata. The client will process these in version order (ie starting
220+ with ` rotate/foo.rotate.1 ` , then ` rotate/foo.rotate.2 ` by first checking for this
221+ version file in a local cache. The client will then fetch the rotate file from
222+ remote. If the remote file is a rotation to null, and is signed with the currently
223+ trusted keys, the client will halt the verification of this metadata and act as if
224+ it is unverified when continuing the update process (and look for metadata from
225+ the next role in the pre-order depth-first search). Otherwise, the client should
226+ ensure that the cached file is identical to the remote version. The client will
227+ then verify the rotate file using the currently trusted public key(s) for this role.
228+ If a rotate
229+ file is successfully verified, the client will update the set of trusted keys for
230+ this role to be the set listed in the rotate files. If key data is missing
231+ or there is a rotation to null, the targets file is invalid and the client will
232+ proceed with the update process as if verification for this role failed (by moving
233+ on to another trusted role for this target, or reporting an error to the user).
234+
235+ This process establishes trust in Alice's new key, and the client can now verify the
236+ signature of Alice's targets file using the new key. In the case that there are
237+ multiple keys for a role, this rotate process can be used to rotate any number of
238+ individual keys, or to add or remove keys. A role ` foo ` can be delegated to with keys
239+ A, B, and C with a threshold of 2. A rotate file can then change the keys for both B
240+ and C by creating a rotation to A, D, and E. Another rotate file can then add an
241+ additional collaborator by rotating to A, D, E, and F.
242+
243+ The delegating role should ensure that all previous rotate files are removed when
244+ it delegates to a new chain of trust. This saves space and simplifies the client
245+ search for rotate files.
225246
226247## Timestamp and snapshot rotation
227248
@@ -234,32 +255,41 @@ files can only be verified after snapshot metadata has been verified. In the TUF
234255workflow, the timestamp and snapshot keys are used before the snapshot metadata
235256is verified, and thus cannot be rotated using the mechanism in this TAP.
236257
258+ ## Interoperability with TAP 4 (Multiple repository consensus)
259+
260+ If multiple repositories use the same role definition, rotate files may need to be
261+ coordinated to ensure consistency. There are two cases when roles are used across
262+ multiple repositories, the first is a mirror of a repository, and the second is
263+ two repositories that have different contents, but share a particular targets
264+ role. In the case of a mirror, all rotate files should be copied, and the
265+ repository can perform as usual, including any rotations. In the second case, the
266+ repository manager must ensure that they have the same set of trusted keys for a
267+ role after all rotations. This can be achieved by copying all rotate files for a
268+ role or by creating a delegation to the final set of trusted keys indicated by
269+ rotate files on another repository. If the latter method is used, note that future
270+ rotate files may not by copied as the version numbers will not start from one.
271+
237272## Interoperability with TAP 3 (multi-role delegations)
238273
239274Multi-role delegations are handled using the same methodology.
240275
241276Let's consider the project baz, initially delegated to a multi-role
242277threshold (of 2) to roles foo, and bar, each of which have a threshold of 2
243278keys. When they want to add a keyid from Dan to the foo role, the current foo
244- keyholders create a foo.rotate.ID.PREV file, where ID is as described above (the
245- SHA256 of the concatenated key ids of foo, and the character 0x32). This contains
246- all previous foo keys, as well as Dan's key and a new threshold. PREV is the
247- SHA256 of "" as this is the first rotation for foo. The file
248- foo.rotate.ID.PREV is signed by at least 2 current keyids of foo.
279+ keyholders create a foo.rotate.1 file. This contains
280+ all previous foo keys, as well as Dan's key and a new threshold. The file
281+ foo.rotate.1 is signed by at least 2 current keyids of foo.
249282The new targets file foo is then signed by a new threshold (again 2) of
250283the new keyids (including Dan) to complete the rotation.
251284
252285Let's assume Bob and Dan signed foo. A client which encounters a
253- delegation to foo first looks for a foo.rotate.ID.PREV file with the
254- keyids and threshold specified in the delegation file and an initial
255- value of "" for the previous rotate file. If this file exists and is
256- properly signed by Alice and Bob, the client uses it to fetch new keys.
286+ delegation to foo first looks for a foo.rotate.1 file. If this file exists
287+ and is properly signed by Alice and Bob, the client uses it to fetch new keys.
257288The client can then verify foo using Bob's and Dan's signature.
258289
259290When Evelyn joins, and the threshold is increased to 3,
260- foo.rotate.ID'.PREV' is created (ID' is the SHA256 of the concatenated old keyids,
261- and 0x32, PREV' is the SHA256 of the previous rotate file), which contains the
262- existing keyids as well as Evelyn's public key, and a threshold value of 3. This
291+ foo.rotate.2 is created, which contains the existing keyids as well as
292+ Evelyn's public key, and a threshold value of 3. This
263293is signed with at least 2 keys from the current set of keyids.
264294
265295## Rotation to Null
@@ -349,13 +379,6 @@ keyids are already listed in the delegation. Our proposal also takes advantage
349379of the existing delegation model in TUF to allow for thresholds of signatures
350380and revocation by a more trusted role.
351381
352- Clashes of rotate file names are unlikely - the role is the first
353- element, followed by "rotate", all key ids in alphabetical order,
354- and the threshold value. Certainly this requires that key ids and
355- roles do not contain any "." - which is used as separator. In addition
356- the inclusion of the SHA256 of the previous rotate file makes collisions
357- even more unlikely.
358-
359382# Backwards compatibility
360383
361384TAP 8 is not backwards compatible since clients have to download and
0 commit comments