66The example code in this file demonstrates how to perform succinct hash bin
77delegation using the low-level Metadata API.
88Succinct hash bin delegation achieves a similar result as using a standard hash
9- bin delegation, but the delegating metadata is smaller resulting in fewer bytes
9+ bin delegation, but the delegating metadata is smaller, resulting in fewer bytes
1010to transfer and parse.
1111
1212See 'basic_repo.py' for a more comprehensive TUF metadata API example.
4040# Succinct hash bin delegation
4141# ============================
4242# Succinct hash bin delegation aims to distribute a large number of target files
43- # over multiple delegated targets metadata roles (bins). The consequence is a
43+ # over multiple delegated targets metadata roles (bins). The consequence is
4444# smaller metadata files and thus a lower network overhead for repository-client
4545# communication.
4646#
4747# The assignment of target files to a target's metadata is done automatically,
4848# based on the byte digest of the target file name.
4949#
50- # The number of the bins, name prefix for all bins and key threshold are all
50+ # The number of bins, name prefix for all bins and key threshold are all
5151# attributes that need to be configured.
5252
5353# Number of bins, bit length and bin number computation
5454# -----------------------------------------------------
55- # The right number of bins depends on the expected number of target files in a
56- # repository. For the purpose of this example we choose:
55+ # Determining the correct number of bins is dependent on the expected number of
56+ # target files in a repository. For the purpose of this example we choose:
5757NUMBER_OF_BINS = 32
5858#
59- # The bit length is the number of bins that will be used to calculate the bin
60- # for each target path. It can be calculated directly from NUMBER_OF_BINS:
59+ # The number of bins will determine the number of bits in a target path
60+ # considered in assigning the target to a bin.
6161BIT_LENGTH = int (math .log2 (NUMBER_OF_BINS ))
6262
6363# Delegated role (bin) name format
7373
7474# Keys and threshold
7575# ------------------
76- # Given that the primary concern of succinct hash bin delegation is to reduce
77- # network overhead it was decided that all bins will be signed by the same
78- # set of one or more signing keys.
79- #
80- # Before generating the keys a decision has to be made about the number of keys
81- # required for signing the bins or in other words the value of the threshold.
82- # For the purpose of this example we choose the threshold to be:
76+ # Succinct hash bin delegation uses the same key(s) to sign all bins. This is
77+ # acceptable because the primary concern of this type of delegation is to reduce
78+ # network overhead. For the purpose of this example only one key is required.
8379THRESHOLD = 1
84- # Note: If THRESHOLD is changed to more than 1 the example should be modified.
8580
8681
8782def create_key () -> Tuple [Key , SSlibSigner ]:
@@ -92,28 +87,19 @@ def create_key() -> Tuple[Key, SSlibSigner]:
9287
9388key , signer = create_key ()
9489
95- # Top level targets instance with succinct hash bin delegation
96- # ------------------------------------------------------------
90+ # Delegating targets role
91+ # -----------------------
92+ # Akin to regular targets delegation, the delegating role ships the public keys
93+ # of the delegated roles. However, instead of providing individual delegation
94+ # information about each role, one single `SuccinctRoles` object is used to
95+ # provide the information for all delegated roles (bins).
96+
9797# NOTE: See "Targets" and "Targets delegation" paragraphs in 'basic_repo.py'
9898# example for more details about the Targets object.
99- #
100- # Now we have all the ingredients needed to create a Targets instance using
101- # succinct hash bin delegation.
102- #
103- # First, we create a Targets metadata instance without any delegations.
10499
105- # We define expire as 7 days from today.
106100expiration_date = datetime .utcnow ().replace (microsecond = 0 ) + timedelta (days = 7 )
107101targets = Metadata (Targets (expires = expiration_date ))
108102
109- # Then, we want to add delegations and with it information about the succinct
110- # hash bin delegations which are represented by SuccinctRoles instance.
111- #
112- # Using succinct hash bin delegations has two restrictions:
113- # 1) no other delegated roles have to be used
114- # 2) only one succinct hash bin delegation can exist for one targets role
115-
116- # We have all information needed to create a SuccinctRoles instance:
117103succinct_roles = SuccinctRoles (
118104 keyids = [],
119105 threshold = THRESHOLD ,
@@ -126,25 +112,17 @@ def create_key() -> Tuple[Key, SSlibSigner]:
126112succinct_roles .keyids .append (key .keyid )
127113delegations_keys_info [key .keyid ] = key
128114
129- # We are ready to define the Delegations instance which we will add to targets.
130- # As mentioned, standard roles are not allowed together with succinct_roles.
131- delegations = Delegations (
115+ targets .signed .delegations = Delegations (
132116 delegations_keys_info , roles = None , succinct_roles = succinct_roles
133117)
134118
135- targets .signed .delegations = delegations
136-
137- # Delegated targets (bins) roles
119+ # Delegated targets roles (bins)
138120# ------------------------------
139- # We have defined the top-level targets metadata instance which utilizes
140- # succinct_roles. With succinct_roles we have defined the bins number, common
141- # bin properties and keys information, but we haven't actually created the
142- # bins targets metadata instances.
121+ # We can use the SuccinctRoles object from the delegating role above to iterate
122+ # over all bin names in the delegation and create the corresponding metadata.
143123
144- # mypy linter requires that we verify that succinct_roles is not None
145- assert targets .signed .delegations .succinct_roles is not None
124+ assert targets .signed .delegations .succinct_roles is not None # make mypy happy
146125
147- # We can get all bin names for a SuccinctRoles instance with get_roles()
148126delegated_bins : Dict [str , Metadata [Targets ]] = {}
149127for delegated_bin_name in targets .signed .delegations .succinct_roles .get_roles ():
150128 delegated_bins [delegated_bin_name ] = Metadata (
@@ -153,7 +131,7 @@ def create_key() -> Tuple[Key, SSlibSigner]:
153131
154132# Add target file inside a delegated role (bin)
155133# ---------------------------------------------
156- # For the purpose of this example we will protect the integrity of this very
134+ # For the purpose of this example we will protect the integrity of this
157135# example script by adding its file info to the corresponding bin metadata.
158136
159137# NOTE: See "Targets" paragraph in 'basic_repo.py' example for more details
@@ -177,10 +155,9 @@ def create_key() -> Tuple[Key, SSlibSigner]:
177155
178156# Sign and persist
179157# ----------------
180- # Sign all metadata and persist to a temporary directory at CWD for review using
181- # versioned file names. Most notably see 'targets.json' and
182- # 'delegated_bin-0d.json'. For more information on versioned file names see:
183- # https://theupdateframework.github.io/specification/latest/#writing-consistent-snapshots
158+ # Sign all metadata and write to a temporary directory at CWD for review using
159+ # versioned file names. Most notably see '1.targets.json' and
160+ # '1.delegated_bin-0d.json'.
184161
185162# NOTE: See "Persist metadata" paragraph in 'basic_repo.py' example for more
186163# details about serialization formats and metadata file name convention.
0 commit comments