Skip to content

Commit 2d82f34

Browse files
committed
Update repository_lib and client/updater to use the canonical json representation when hashing snapshot information.
By using the canonical json representation, this commit ensures that the hash will be consistent across different python versions. this commit additionally updates the test data to use the correct hashes. Signed-off-by: marinamoore <[email protected]>
1 parent afdbf8c commit 2d82f34

7 files changed

Lines changed: 25 additions & 16 deletions

File tree

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
{
22
"leaf_contents": {
3+
"name": "role1",
34
"version": 1
45
},
56
"merkle_path": {
6-
"0": "d0657b1fe8cd74976421241692e36b86ebd8f923a3f71ec99dbcacac319a11eb"
7+
"0": "3bd2912d01accd816767dcde96a2b470dc5bb51cefe3b3aeb3aca7fdc1704d6b",
8+
"1": "70304860310d2c6f0a05f2ccbfb49a4a6d6d3c7a9ff9c93e0b91b2e0ab7fff97"
79
},
810
"path_directions": {
9-
"0": 1
11+
"0": -1,
12+
"1": -1
1013
}
1114
}

tests/repository_data/repository/metadata/role2-snapshot.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
{
22
"leaf_contents": {
3+
"name": "role2",
34
"version": 1
45
},
56
"merkle_path": {
6-
"0": "abcfdd2bed858c5d7e8866a21bbdee0ca94cc03fd61f9a8c7ccbe4e50a78044a",
7-
"1": "d5d4546f9bfcce78a079fff48828b922091b5be9e874d5d2ce075e314dd19e13"
7+
"0": "9a8cf4b3e3cf611d339867f295792c3105d3d8ebfcd559607f9528ba7511e52a",
8+
"1": "70304860310d2c6f0a05f2ccbfb49a4a6d6d3c7a9ff9c93e0b91b2e0ab7fff97"
89
},
910
"path_directions": {
1011
"0": 1,
Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
{
22
"leaf_contents": {
3+
"name": "targets",
34
"version": 1
45
},
56
"merkle_path": {
6-
"0": "4d9f52a07628625e664bfd96868b69d5b4e81debf3f00ed3940e00cd8dc3da70",
7-
"1": "d5d4546f9bfcce78a079fff48828b922091b5be9e874d5d2ce075e314dd19e13"
7+
"0": "30e11c75a8fa88fd36cc2a4796c5c9f405c9ae52b7adf4180d1c351141e5037a"
88
},
99
"path_directions": {
10-
"0": -1,
11-
"1": -1
10+
"0": 1
1211
}
1312
}

tests/repository_data/repository/metadata/timestamp-merkle.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22
"signatures": [
33
{
44
"keyid": "8a1c4a3ac2d515dec982ba9910c5fd79b91ae57f625b9cff25d06bf0a61c1758",
5-
"sig": "c900d68461b8defb7d5d081376576c54f6e619ef8fde33d07b88e2763f123fbb10844168b7dfc638e0b137a8289bf56253a528e4b771ea5277182950f1517c0c"
5+
"sig": "1790a53390ab9928ba5c46e7a30a4e0348976e26f34d8cdd29ee11d644276dfc72e3fff6d1a7a913a42a1443cda12a738a3e4803818e970446a91e0e99f24601"
66
}
77
],
88
"signed": {
99
"_type": "timestamp",
1010
"expires": "2030-01-01T00:00:00Z",
11-
"merkle_root": "2b232a308f285d2ef594fa4410d3982f3982e33c28cd73fe1f23a0014be7da77",
11+
"merkle_root": "76eb3066cb278633fda18fa6e3ae33d783ff154e813e2752eb7bc8b65568a41b",
1212
"meta": {
1313
"snapshot.json": {
1414
"hashes": {

tests/test_updater.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1783,7 +1783,9 @@ def test_snapshot_merkle(self):
17831783

17841784
# Test verify merkle path
17851785
snapshot_info = repository_updater._verify_merkle_path('targets')
1786+
self.assertEqual(snapshot_info['version'], 1)
17861787

1788+
snapshot_info = repository_updater._verify_merkle_path('role1')
17871789
self.assertEqual(snapshot_info['version'], 1)
17881790

17891791
# verify merkle path with invalid role

tuf/client/updater.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1900,8 +1900,9 @@ def _verify_merkle_path(self, metadata_role):
19001900

19011901
# hash the contents to determine the leaf hash in the merkle tree
19021902
contents = snapshot_merkle['leaf_contents']
1903+
json_contents = securesystemslib.formats.encode_canonical(contents)
19031904
digest_object = securesystemslib.hash.digest()
1904-
digest_object.update((metadata_role + str(contents) + '0').encode('utf-8'))
1905+
digest_object.update((json_contents).encode('utf-8'))
19051906
node_hash = digest_object.hexdigest()
19061907

19071908
# For each hash in the merkle_path, determine if the current node is

tuf/repository_lib.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1572,7 +1572,7 @@ def __init__(self, left, right):
15721572

15731573
left.set_parent(self)
15741574
right.set_parent(self)
1575-
digest_object = securesystemslib.hash.digest()
1575+
digest_object = securesystemslib.hash.digest(algorithm=HASH_FUNCTION)
15761576

15771577
digest_object.update((left.hash() + right.hash()).encode('utf-8'))
15781578

@@ -1605,16 +1605,19 @@ class Leaf(Node):
16051605

16061606
def __init__(self, name, contents, digest = None):
16071607
super(Leaf, self).__init__()
1608+
# Include the name to ensure the hash differs between elements and cannot be replayed
1609+
contents["name"] = name
16081610
self._contents = contents
16091611
self._name = name
16101612

16111613
if digest:
16121614
self._hash = digest
16131615
else:
1614-
digest_object = securesystemslib.hash.digest()
1615-
# Append a 0 for reverse preimage protection
1616-
# Include the name to ensure the hash differs between elements
1617-
digest_object.update((name + str(contents) + '0').encode('utf-8'))
1616+
digest_object = securesystemslib.hash.digest(algorithm=HASH_FUNCTION)
1617+
# Hash the canonical json form of the data to ensure consistency
1618+
json_contents = securesystemslib.formats.encode_canonical(contents)
1619+
1620+
digest_object.update(json_contents.encode('utf-8'))
16181621
self._hash = digest_object.hexdigest()
16191622

16201623
def name(self):

0 commit comments

Comments
 (0)