[tor-commits] [stem/master] stem.descriptor.certificate unit tests

atagar at torproject.org atagar at torproject.org
Thu Mar 30 04:18:02 UTC 2017


commit 311c4d7bab40c3f3bb80c9e52a217a390e635aab
Author: Patrick O'Doherty <p at trickod.com>
Date:   Tue Feb 7 20:23:49 2017 -0800

    stem.descriptor.certificate unit tests
    
    Unit tests to ensure that invalid certificate data raises the
    appropriately descriptive ValueError when using the _parse_certificate
    and _parse_extensions functions provided by stem.descriptor.certificate
---
 stem/descriptor/certificate.py      |   6 +-
 test/settings.cfg                   |   1 +
 test/unit/descriptor/certificate.py | 108 ++++++++++++++++++++++++++++++++++++
 3 files changed, 112 insertions(+), 3 deletions(-)

diff --git a/stem/descriptor/certificate.py b/stem/descriptor/certificate.py
index 63ebace..ff78538 100644
--- a/stem/descriptor/certificate.py
+++ b/stem/descriptor/certificate.py
@@ -5,7 +5,7 @@
 Parsing for the Tor server descriptor Ed25519 Certificates, which is used to
 validate the Ed25519 key used to sign the relay descriptor.
 
-Certificates can optionally contain CertificateExtension objects depending on their type and purpose. Currently Ed25519KeyCertificate certificates will contain one SignedWithEd25519KeyCertificateExtensio
+Certificates can optionally contain CertificateExtension objects depending on their type and purpose. Currently Ed25519KeyCertificate certificates will contain one SignedWithEd25519KeyCertificateExtension
 
 
 **Module Overview:**
@@ -82,9 +82,9 @@ def _parse_extensions(raw_contents):
   extensions = []
   extension_bytes = raw_contents[STANDARD_ATTRIBUTES_LENGTH:-SIGNATURE_LENGTH]
   while len(extension_bytes) > 0:
-    ext_length = _bytes_to_long(extension_bytes[0:2])
-    ext_type, ext_flags = extension_bytes[2:CERTIFICATE_FLAGS_LENGTH]
     try:
+      ext_length = _bytes_to_long(extension_bytes[0:2])
+      ext_type, ext_flags = extension_bytes[2:CERTIFICATE_FLAGS_LENGTH]
       ext_data = extension_bytes[CERTIFICATE_FLAGS_LENGTH:(CERTIFICATE_FLAGS_LENGTH + ext_length)]
     except:
       raise ValueError('Certificate contained truncated extension')
diff --git a/test/settings.cfg b/test/settings.cfg
index c8172f6..558487d 100644
--- a/test/settings.cfg
+++ b/test/settings.cfg
@@ -190,6 +190,7 @@ test.unit_tests
 |test.unit.descriptor.networkstatus.document_v3.TestNetworkStatusDocument
 |test.unit.descriptor.networkstatus.bridge_document.TestBridgeNetworkStatusDocument
 |test.unit.descriptor.hidden_service_descriptor.TestHiddenServiceDescriptor
+|test.unit.descriptor.certificate.TestCertificate
 |test.unit.exit_policy.rule.TestExitPolicyRule
 |test.unit.exit_policy.policy.TestExitPolicy
 |test.unit.version.TestVersion
diff --git a/test/unit/descriptor/certificate.py b/test/unit/descriptor/certificate.py
new file mode 100644
index 0000000..450685f
--- /dev/null
+++ b/test/unit/descriptor/certificate.py
@@ -0,0 +1,108 @@
+"""
+Unit tests for stem.descriptor.certificate.
+"""
+
+import unittest
+
+import stem.descriptor.certificate
+
+import nacl.signing
+import nacl.encoding
+
+
+class TestCertificate(unittest.TestCase):
+
+  def test_with_invalid_version(self):
+    cert_bytes = '\x02\x04'
+    self.assertRaisesRegexp(
+      ValueError,
+      'Unknown Certificate version',
+      stem.descriptor.certificate._parse_certificate,
+      cert_bytes,
+      None
+    )
+
+  def test_with_invalid_type(self):
+    cert_bytes = '\x01\x07'
+    self.assertRaisesRegexp(
+      ValueError,
+      'Unknown Certificate type',
+      stem.descriptor.certificate._parse_certificate,
+      cert_bytes,
+      None
+    )
+
+  def test_parse_extensions_truncated_extension(self):
+    cert_bytes = '\x00' * 39  # First 40 bytes are standard fields
+    cert_bytes += '\x01'  # n_extensions = 1
+    cert_bytes += '\x00\x08'  # extension length = 8 bytes
+    cert_bytes += stem.descriptor.certificate.SIGNATURE_LENGTH * '\x00'  # pad empty signature block
+
+    self.assertRaisesRegexp(
+      ValueError,
+      'Certificate contained truncated extension',
+      stem.descriptor.certificate._parse_extensions,
+      cert_bytes
+     )
+
+  def test_parse_extensions_invalid_certificate_extension_type(self):
+    cert_bytes = '\x00' * 39  # First 40 bytes are standard fields
+    cert_bytes += '\x01'   # n_extensions = 1
+    cert_bytes += '\x00\x08'  # extension length = 8 bytes
+    cert_bytes += '\x00' * 6  # pad out to 8 bytes
+    cert_bytes += stem.descriptor.certificate.SIGNATURE_LENGTH * '\x00'  # pad empty signature block
+
+    self.assertRaisesRegexp(
+      ValueError,
+      'Invalid certificate extension type:',
+      stem.descriptor.certificate._parse_extensions,
+      cert_bytes
+     )
+
+  def test_parse_extensions_invalid_n_extensions_count(self):
+    cert_bytes = '\x00' * 39  # First 40 bytes are standard fields
+    cert_bytes += '\x02'    # n_extensions = 2
+    cert_bytes += '\x00\x08'  # extension length = 8 bytes
+    cert_bytes += '\x04'    # certificate type
+    cert_bytes += '\x00' * 5  # pad out to 8 bytes
+    cert_bytes += stem.descriptor.certificate.SIGNATURE_LENGTH * '\x00'  # pad empty signature block
+
+    self.assertRaisesRegexp(
+      ValueError,
+      'n_extensions was 2 but parsed 1',
+      stem.descriptor.certificate._parse_extensions,
+      cert_bytes
+     )
+
+  def test_ed25519_key_certificate_without_extensions(self):
+    cert_bytes = '\x01\x04' + '\x00' * 37  # First 40 bytes are standard fields
+    cert_bytes += '\x00'   # n_extensions = 0
+    cert_bytes += stem.descriptor.certificate.SIGNATURE_LENGTH * '\x00'  # pad empty signature block
+
+    self.assertRaisesRegexp(
+      ValueError,
+      'Ed25519KeyCertificate missing SignedWithEd25519KeyCertificateExtension extension',
+      stem.descriptor.certificate._parse_certificate,
+      cert_bytes,
+      None,
+      validate = True
+     )
+
+  def test_certificate_with_invalid_signature(self):
+    master_key = nacl.signing.SigningKey.generate()
+    master_key_base64 = master_key.encode(nacl.encoding.Base64Encoder)
+
+    cert_bytes = '\x01\x04' + '\x00' * 37  # 40 byte preamble of standard fields
+    cert_bytes += '\x01'  # n_extensions = 1
+    cert_bytes += '\x00\x08'  # extentsion length = 8 bytes
+    cert_bytes += '\x04' + '\x00' * 5  # certificate type + padding out to 8 bytes
+    cert_bytes += stem.descriptor.certificate.SIGNATURE_LENGTH * '\x00'  # empty signature block
+
+    self.assertRaisesRegexp(
+      ValueError,
+      'Ed25519KeyCertificate signature invalid',
+      stem.descriptor.certificate._parse_certificate,
+      cert_bytes,
+      master_key_base64,
+      validate = True
+    )





More information about the tor-commits mailing list