@@ -339,6 +339,37 @@ def test_new_timestamp_expired(self) -> None:
339
339
340
340
self ._assert_files_exist ([Root .type ])
341
341
342
+ def test_new_timestamp_fast_foward_recovery (self ) -> None :
343
+ """Test timestamp fast-forward recovery using key rotation.
344
+
345
+ The timestamp recovery is made by the following steps
346
+ - Remove the timestamp key
347
+ - Create and add a new key for timestamp
348
+ - Bump and publish root
349
+ - Rollback the timestamp version
350
+ """
351
+
352
+ # attacker updates to a higher version
353
+ self .sim .timestamp .version = 99999
354
+
355
+ # client refreshes the metadata and see the new timestamp version
356
+ self ._run_refresh ()
357
+ self ._assert_version_equals (Timestamp .type , 99999 )
358
+
359
+ # repo add new timestamp keys and recovers the timestamp version
360
+ self .sim .root .roles ["timestamp" ].keyids .clear ()
361
+ self .sim .signers ["timestamp" ].clear ()
362
+ key , signer = self .sim .create_key ()
363
+ self .sim .root .add_key ("timestamp" , key )
364
+ self .sim .add_signer ("timestamp" , signer )
365
+ self .sim .root .version += 1
366
+ self .sim .publish_root ()
367
+ self .sim .timestamp .version = 1
368
+
369
+ # client refresh the metadata and see the initial timestamp version
370
+ self ._run_refresh ()
371
+ self ._assert_version_equals (Timestamp .type , 1 )
372
+
342
373
def test_new_snapshot_hash_mismatch (self ) -> None :
343
374
# Check against timestamp role’s snapshot hash
344
375
0 commit comments