commit e1772bb9ad9ad2f6f085e2c0f489214d2f7fd6ee Author: Damian Johnson atagar@torproject.org Date: Fri Nov 23 12:14:12 2012 -0800
Revised behavior for document signature methods
The spec has been revised to explain how signature methods worked. I had assumed that they were included in microdescritor consensuses and excluded from standard consensuses. Turns out however that they can be included with both and, if excluded, have a default value of 'sha1'. This is much nicer from a parsing and behavior standpoint.
bug report: https://trac.torproject.org/7072 fix: https://gitweb.torproject.org/torspec.git/commitdiff/96427e8 --- stem/descriptor/networkstatus.py | 22 +++--------- test/integ/descriptor/networkstatus.py | 4 +- test/mocking.py | 5 --- test/unit/descriptor/networkstatus/document_v3.py | 37 +++++++-------------- 4 files changed, 19 insertions(+), 49 deletions(-)
diff --git a/stem/descriptor/networkstatus.py b/stem/descriptor/networkstatus.py index 0c08611..ca6aca2 100644 --- a/stem/descriptor/networkstatus.py +++ b/stem/descriptor/networkstatus.py @@ -768,19 +768,12 @@ class _DocumentFooter(object): raise ValueError("A network status document's 'bandwidth-weights' entries should be '%s', got '%s'" % (expected_label, actual_label)) elif keyword == "directory-signature": for sig_value, block_contents in values: - if not header.is_microdescriptor: - expected_spaces = 1 - format_label = 'directory-signature FINGERPRINT KEY_DIGEST' - else: - expected_spaces = 2 - format_label = 'directory-signature METHOD FINGERPRINT KEY_DIGEST' - - if sig_value.count(" ") != expected_spaces or not block_contents: + if not sig_value.count(" ") in (1, 2) or not block_contents: if not validate: continue - raise ValueError("Authority signatures in a network status document are expected to be of the form '%s\nSIGNATURE', got:\n%s\n%s" % (format_label, sig_value, block_contents)) + raise ValueError("Authority signatures in a network status document are expected to be of the form 'directory-signature [METHOD] FINGERPRINT KEY_DIGEST\nSIGNATURE', got:\n%s\n%s" % (sig_value, block_contents))
- if not header.is_microdescriptor: - method = None + if sig_value.count(" ") == 1: + method = 'sha1' # default if none was provided fingerprint, key_digest = sig_value.split(" ", 1) else: method, fingerprint, key_digest = sig_value.split(" ", 2) @@ -1232,8 +1225,7 @@ class DocumentSignature(object): """ Directory signature of a v3 network status document.
- :var str method: method used to make the signature, this only appears in - microdescriptor consensuses + :var str method: algorithm used to make the signature :var str identity: fingerprint of the authority that made the signature :var str key_digest: digest of the signing key :var str signature: document signature @@ -1253,10 +1245,6 @@ class DocumentSignature(object): if not stem.util.tor_tools.is_valid_fingerprint(key_digest): raise ValueError("Malformed key digest (%s) in the document signature" % (key_digest))
- # TODO: The method field is undocumented so I'm just guessing how we should - # handle it. Ticket for clarification... - # https://trac.torproject.org/7072 - self.method = method self.identity = identity self.key_digest = key_digest diff --git a/test/integ/descriptor/networkstatus.py b/test/integ/descriptor/networkstatus.py index 1b70898..84a1901 100644 --- a/test/integ/descriptor/networkstatus.py +++ b/test/integ/descriptor/networkstatus.py @@ -189,7 +189,7 @@ I/TJmV928na7RLZe2mGHCAW3VQOvV+QkCfj05VZ8CsY=
signature = document.signatures[0] self.assertEquals(8, len(document.signatures)) - self.assertEquals(None, signature.method) + self.assertEquals("sha1", signature.method) self.assertEquals("14C131DFC5C6F93646BE72FA1401C02A8DF2E8B4", signature.identity) self.assertEquals("BF112F1C6D5543CFD0A32215ACABD4197B5279AD", signature.key_digest) self.assertEquals(expected_signature, signature.signature) @@ -400,7 +400,7 @@ DnN5aFtYKiTc19qIC7Nmo+afPdDEf0MlJvEOP5EWl3w=
signature = document.signatures[0] self.assertEquals(1, len(document.signatures)) - self.assertEquals(None, signature.method) + self.assertEquals("sha1", signature.method) self.assertEquals("27B6B5996C426270A5C95488AA5BCEB6BCC86956", signature.identity) self.assertEquals("D5C30C15BB3F1DA27669C2D88439939E8F418FCF", signature.key_digest) self.assertEquals(expected_signature, signature.signature) diff --git a/test/mocking.py b/test/mocking.py index d1b92db..e48ce64 100644 --- a/test/mocking.py +++ b/test/mocking.py @@ -759,11 +759,6 @@ def get_network_status_document_v3(attr = None, exclude = (), authorities = None "consensus-method": "9", }
- if "microdesc" in attr.get("network-status-version", ""): - extra_defaults.update({ - "directory-signature": "sha256 " + NETWORK_STATUS_DOCUMENT_FOOTER[2][1], - }) - for k, v in extra_defaults.items(): if not (k in attr or (exclude and k in exclude)): attr[k] = v diff --git a/test/unit/descriptor/networkstatus/document_v3.py b/test/unit/descriptor/networkstatus/document_v3.py index 11c9a9f..0396754 100644 --- a/test/unit/descriptor/networkstatus/document_v3.py +++ b/test/unit/descriptor/networkstatus/document_v3.py @@ -635,39 +635,26 @@ class TestNetworkStatusDocument(unittest.TestCase):
def test_microdescriptor_signature(self): """ - The 'directory-signature' lines for normal and microdescriptor conensuses - differ slightly in their format. + The 'directory-signature' lines both with and without a defined method for + the signature format. """
- # including a microdescriptor flavored 'directory-signature' line should work + # including the signature method field should work
- document = get_network_status_document_v3({"network-status-version": "3 microdesc"}) - self.assertEqual('sha256', document.signatures[0].method) - - # include a standard 'directory-signature' line in a microdescriptor - # consensus - - content = get_network_status_document_v3({ + document = get_network_status_document_v3({ "network-status-version": "3 microdesc", - "directory-signature": NETWORK_STATUS_DOCUMENT_FOOTER[2][1], - }, content = True) - - self.assertRaises(ValueError, NetworkStatusDocumentV3, content) - - document = NetworkStatusDocumentV3(content, validate = False) - self.assertEqual([], document.signatures) + "directory-signature": "sha256 " + NETWORK_STATUS_DOCUMENT_FOOTER[2][1], + })
- # includes a microdescriptor flavored 'directory-signature' line in a - # normal consensus + self.assertEqual('sha256', document.signatures[0].method)
- content = get_network_status_document_v3({ - "directory-signature": "sha256 " + NETWORK_STATUS_DOCUMENT_FOOTER[2][1], - }, content = True) + # excluding the method should default to sha1
- self.assertRaises(ValueError, NetworkStatusDocumentV3, content) + document = get_network_status_document_v3({ + "network-status-version": "3 microdesc", + })
- document = NetworkStatusDocumentV3(content, validate = False) - self.assertEqual([], document.signatures) + self.assertEqual('sha1', document.signatures[0].method)
def test_malformed_signature(self): """
tor-commits@lists.torproject.org