[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[tor-commits] [stem/master] Merge CertType enumerations



commit 359d6833de7ac2481aa0ab5c47a1019514060dd6
Author: Damian Johnson <atagar@xxxxxxxxxxxxxx>
Date:   Thu Oct 17 16:33:05 2019 -0700

    Merge CertType enumerations
    
    I accidently had two enumerations for the same thing...
    
      stem.client.datatype.CertType
      stem.descriptor.certificate.CertType
    
    The first is the better enumeration in that it's integer backed. Expanding the
    values it encompasses and deprecating the certificate.py copy.
---
 stem/client/datatype.py                   | 51 +++++++++++++++++-------
 stem/descriptor/certificate.py            | 65 +++++++++++++++----------------
 stem/descriptor/hidden_service.py         |  5 ++-
 test/unit/client/cell.py                  |  6 +--
 test/unit/client/certificate.py           |  2 +-
 test/unit/descriptor/certificate.py       | 12 ++++--
 test/unit/descriptor/server_descriptor.py |  5 ++-
 7 files changed, 87 insertions(+), 59 deletions(-)

diff --git a/stem/client/datatype.py b/stem/client/datatype.py
index 76957819..73def712 100644
--- a/stem/client/datatype.py
+++ b/stem/client/datatype.py
@@ -83,16 +83,33 @@ users.** See our :class:`~stem.client.Relay` the API you probably want.
 
 .. data:: CertType (enum)
 
-  Relay certificate type.
-
-  ===================== ===========
-  CertType              Description
-  ===================== ===========
-  **LINK**              link key certificate certified by RSA1024 identity
-  **IDENTITY**          RSA1024 Identity certificate
-  **AUTHENTICATE**      RSA1024 AUTHENTICATE cell link certificate
-  **UNKNOWN**           unrecognized certificate type
-  ===================== ===========
+  Certificate purpose. For more information see...
+
+    * `tor-spec.txt <https://gitweb.torproject.org/torspec.git/tree/tor-spec.txt>`_ section 4.2
+    * `cert-spec.txt <https://gitweb.torproject.org/torspec.git/tree/cert-spec.txt>`_ section A.1
+    * `rend-spec-v3.txt <https://gitweb.torproject.org/torspec.git/tree/rend-spec-v3.txt>`_ appendix E
+
+  .. versionchanged:: 1.8.0
+     Added the ED25519_SIGNING, LINK_CERT, ED25519_AUTHENTICATE,
+     ED25519_IDENTITY, HS_V3_DESC_SIGNING, HS_V3_INTRO_AUTH, NTOR_ONION_KEY,
+     and HS_V3_NTOR_ENC certificate types.
+
+  ========================= ===========
+  CertType                  Description
+  ========================= ===========
+  **LINK**                  link key certificate certified by RSA1024 identity
+  **IDENTITY**              RSA1024 Identity certificate
+  **AUTHENTICATE**          RSA1024 AUTHENTICATE cell link certificate
+  **ED25519_SIGNING**       Ed25519 signing key, signed with identity key
+  **LINK_CERT**             TLS link certificate, signed with ed25519 signing key
+  **ED25519_AUTHENTICATE**  Ed25519 AUTHENTICATE cell key, signed with ed25519 signing key
+  **ED25519_IDENTITY**      Ed25519 identity, signed with RSA identity
+  **HS_V3_DESC_SIGNING**    hidden service v3 short-term descriptor signing key
+  **HS_V3_INTRO_AUTH**      hidden service v3 introduction point authentication key
+  **NTOR_ONION_KEY**        ntor onion key cross-certifying ed25519 identity key
+  **HS_V3_NTOR_ENC**        hidden service v3 ntor-extra encryption key
+  **UNKNOWN**               unrecognized certificate type
+  ========================= ===========
 
 .. data:: CloseReason (enum)
 
@@ -201,9 +218,17 @@ RelayCommand = _IntegerEnum(
 )
 
 CertType = _IntegerEnum(
-  ('LINK', 1),
-  ('IDENTITY', 2),
-  ('AUTHENTICATE', 3),
+  ('LINK', 1),                  # (tor-spec.txt section 4.2)
+  ('IDENTITY', 2),              # (tor-spec.txt section 4.2)
+  ('AUTHENTICATE', 3),          # (tor-spec.txt section 4.2)
+  ('ED25519_SIGNING', 4),       # (prop220 section 4.2)
+  ('LINK_CERT', 5),             # (prop220 section 4.2)
+  ('ED25519_AUTHENTICATE', 6),  # (prop220 section 4.2)
+  ('ED25519_IDENTITY', 7),      # (prop220 section 4.2)
+  ('HS_V3_DESC_SIGNING', 8),    # (rend-spec-v3.txt, "DESC_OUTER" description)
+  ('HS_V3_INTRO_AUTH', 9),      # (rend-spec-v3.txt, "auth-key" description)
+  ('NTOR_ONION_KEY', 10),       # (dir-spec.txt, "ntor-onion-key-crosscert" description)
+  ('HS_V3_NTOR_ENC', 11),       # (rend-spec-v3.txt, "enc-key-cert" description)
 )
 
 CloseReason = _IntegerEnum(
diff --git a/stem/descriptor/certificate.py b/stem/descriptor/certificate.py
index 05e0eefb..c0897b13 100644
--- a/stem/descriptor/certificate.py
+++ b/stem/descriptor/certificate.py
@@ -27,14 +27,14 @@ used to for a variety of purposes...
 
 .. data:: CertType (enum)
 
-  Purpose of Ed25519 certificate. As new certificate versions are added this
-  enumeration will expand.
-
-  For more information see...
+  Purpose of Ed25519 certificate. For more information see...
 
     * `cert-spec.txt <https://gitweb.torproject.org/torspec.git/tree/cert-spec.txt>`_ section A.1
     * `rend-spec-v3.txt <https://gitweb.torproject.org/torspec.git/tree/rend-spec-v3.txt>`_ appendix E
 
+  .. deprecated:: 1.8.0
+     Replaced with :data:`stem.client.datatype.CertType`
+
   ========================  ===========
   CertType                  Description
   ========================  ===========
@@ -80,19 +80,25 @@ import stem.descriptor.hidden_service
 import stem.descriptor.server_descriptor
 import stem.util.enum
 import stem.util.str_tools
-import stem.util
 
 from stem.client.datatype import Size
-from cryptography.hazmat.primitives import serialization
+
+# TODO: Importing under an alternate name until we can deprecate our redundant
+# CertType enum in Stem 2.x.
+
+from stem.client.datatype import CertType as ClientCertType
 
 ED25519_HEADER_LENGTH = 40
 ED25519_SIGNATURE_LENGTH = 64
 
 CertType = stem.util.enum.UppercaseEnum(
-  'RESERVED_0', 'RESERVED_1', 'RESERVED_2', 'RESERVED_3',
-  'SIGNING', 'LINK_CERT', 'AUTH', 'RESERVED_RSA',
-  'HS_V3_DESC_SIGNING', 'HS_V3_INTRO_AUTH', 'RESERVED_0A',
-  'HS_V3_INTRO_ENC', 'HS_V3_NTOR_ENC')
+  'SIGNING',
+  'LINK_CERT',
+  'AUTH',
+  'HS_V3_DESC_SIGNING',
+  'HS_V3_INTRO_AUTH',
+  'HS_V3_INTRO_ENCRYPT',
+)
 
 ExtensionType = stem.util.enum.Enum(('HAS_SIGNING_KEY', 4),)
 ExtensionFlag = stem.util.enum.UppercaseEnum('AFFECTS_VALIDATION', 'UNKNOWN')
@@ -159,7 +165,6 @@ class Ed25519Certificate(object):
     def _parse(descriptor, entries):
       value, block_type, block_contents = entries[keyword][0]
 
-      # XXX ATAGAR This ValueError never actually surfaces if it triggers...
       if not block_contents or block_type != 'ED25519 CERT':
         raise ValueError("'%s' should be followed by a ED25519 CERT block, but was a %s" % (keyword, block_type))
 
@@ -176,7 +181,8 @@ class Ed25519CertificateV1(Ed25519Certificate):
   Version 1 Ed25519 certificate, which are used for signing tor server
   descriptors.
 
-  :var CertType type: certificate purpose
+  :var stem.client.datatype.CertType type: certificate purpose
+  :var int type_int: integer value of the certificate purpose
   :var datetime expiration: expiration of the certificate
   :var int key_type: format of the key
   :var bytes key: key content
@@ -190,17 +196,14 @@ class Ed25519CertificateV1(Ed25519Certificate):
     if len(decoded) < ED25519_HEADER_LENGTH + ED25519_SIGNATURE_LENGTH:
       raise ValueError('Ed25519 certificate was %i bytes, but should be at least %i' % (len(decoded), ED25519_HEADER_LENGTH + ED25519_SIGNATURE_LENGTH))
 
-    cert_type = stem.util.str_tools._to_int(decoded[1:2])
-    try:
-      self.type = CertType.keys()[cert_type]
-    except IndexError:
-      raise ValueError('Certificate has wrong cert type')
-
-    # Catch some invalid cert types
-    if self.type in ('RESERVED_0', 'RESERVED_1', 'RESERVED_2', 'RESERVED_3'):
-      raise ValueError('Ed25519 certificate cannot have a type of %i. This is reserved to avoid conflicts with tor CERTS cells.' % cert_type)
-    elif self.type == ('RESERVED_RSA'):
+    self.type, self.type_int = ClientCertType.get(stem.util.str_tools._to_int(decoded[1:2]))
+
+    if self.type in (ClientCertType.LINK, ClientCertType.IDENTITY, ClientCertType.AUTHENTICATE):
+      raise ValueError('Ed25519 certificate cannot have a type of %i. This is reserved for CERTS cells.' % self.type_int)
+    elif self.type == ClientCertType.ED25519_IDENTITY:
       raise ValueError('Ed25519 certificate cannot have a type of 7. This is reserved for RSA identity cross-certification.')
+    elif self.type == ClientCertType.UNKNOWN:
+      raise ValueError('Ed25519 certificate type %i is unrecognized' % self.type_int)
 
     # expiration time is in hours since epoch
     try:
@@ -363,8 +366,8 @@ class MyED25519Certificate(object):
                version=1):
     """
     :var int version
-    :var int cert_type
-    :var CertType cert_type
+    :var stem.client.datatype.CertType cert_type
+    :var int cert_type_int
     :var datetime expiration_date
     :var int cert_key_type
     :var ED25519PublicKey certified_pub_key
@@ -372,7 +375,7 @@ class MyED25519Certificate(object):
     :var bool include_signing_key
     """
     self.version = version
-    self.cert_type = cert_type
+    self.cert_type, self.cert_type_int = ClientCertType.get(cert_type)
     self.expiration_date = expiration_date
     self.cert_key_type = cert_key_type
     self.certified_pub_key = certified_pub_key
@@ -391,6 +394,7 @@ class MyED25519Certificate(object):
     Build the cert extensions part of the certificate
     """
 
+    from cryptography.hazmat.primitives import serialization
     n_extensions = 0
 
     # If we need to include the signing key, let's create the extension body
@@ -423,18 +427,11 @@ class MyED25519Certificate(object):
 
   def encode(self):
     """Return a bytes representation of this certificate."""
+    from cryptography.hazmat.primitives import serialization
     obj = bytearray()
 
-    # Encode VERSION
     obj += Size.CHAR.pack(self.version)
-
-    # Encode CERT_TYPE
-    try:
-      cert_type_int = CertType.index_of(self.cert_type)
-    except ValueError:
-      raise ValueError("Bad cert type %s" % self.cert_type)
-
-    obj += Size.CHAR.pack(cert_type_int)
+    obj += Size.CHAR.pack(self.cert_type_int)
 
     # Encode EXPIRATION_DATE
     expiration_seconds_since_epoch = stem.util.datetime_to_unix(self.expiration_date)
diff --git a/stem/descriptor/hidden_service.py b/stem/descriptor/hidden_service.py
index 49009a6a..1a2ce69c 100644
--- a/stem/descriptor/hidden_service.py
+++ b/stem/descriptor/hidden_service.py
@@ -45,8 +45,9 @@ import stem.util.connection
 import stem.util.str_tools
 import stem.util.tor_tools
 
+from stem.client.datatype import CertType
 from stem.descriptor import hsv3_crypto
-from stem.descriptor.certificate import Ed25519Certificate, CertType
+from stem.descriptor.certificate import Ed25519Certificate
 
 from cryptography.hazmat.primitives import serialization
 from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
@@ -255,7 +256,7 @@ class IntroductionPointV3(object):
     body += b'enc-key ntor %s\n' % (base64.b64encode(enc_key_bytes))
 
     # Build enc key cert (this does not actually need to certify anything because of #29583)
-    enc_key_cert = stem.descriptor.certificate.MyED25519Certificate(cert_type = CertType.HS_V3_INTRO_ENC, expiration_date = cert_expiration_date, cert_key_type = 1, certified_pub_key = self.auth_key, signing_priv_key = descriptor_signing_privkey, include_signing_key = True)
+    enc_key_cert = stem.descriptor.certificate.MyED25519Certificate(cert_type = CertType.HS_V3_NTOR_ENC, expiration_date = cert_expiration_date, cert_key_type = 1, certified_pub_key = self.auth_key, signing_priv_key = descriptor_signing_privkey, include_signing_key = True)
     enc_key_cert_b64_blob = enc_key_cert.encode_for_descriptor()
     body += b'enc-key-cert\n%s\n' % (enc_key_cert_b64_blob)
 
diff --git a/test/unit/client/cell.py b/test/unit/client/cell.py
index 22843799..33df79a7 100644
--- a/test/unit/client/cell.py
+++ b/test/unit/client/cell.py
@@ -148,9 +148,9 @@ class TestCell(unittest.TestCase):
     expected_certs = (
       (CertType.LINK, 1, b'0\x82\x02F0\x82\x01\xaf'),
       (CertType.IDENTITY, 2, b'0\x82\x01\xc90\x82\x012'),
-      (CertType.UNKNOWN, 4, b'\x01\x04\x00\x06m\x1f'),
-      (CertType.UNKNOWN, 5, b'\x01\x05\x00\x06m\n\x01'),
-      (CertType.UNKNOWN, 7, b'\x1a\xa5\xb3\xbd\x88\xb1C'),
+      (CertType.ED25519_SIGNING, 4, b'\x01\x04\x00\x06m\x1f'),
+      (CertType.LINK_CERT, 5, b'\x01\x05\x00\x06m\n\x01'),
+      (CertType.ED25519_IDENTITY, 7, b'\x1a\xa5\xb3\xbd\x88\xb1C'),
     )
 
     content = test_data('new_link_cells')
diff --git a/test/unit/client/certificate.py b/test/unit/client/certificate.py
index a15779f5..196dd075 100644
--- a/test/unit/client/certificate.py
+++ b/test/unit/client/certificate.py
@@ -13,7 +13,7 @@ class TestCertificate(unittest.TestCase):
       ((1, b'\x7f\x00\x00\x01'), (CertType.LINK, 1, b'\x7f\x00\x00\x01')),
       ((2, b'\x7f\x00\x00\x01'), (CertType.IDENTITY, 2, b'\x7f\x00\x00\x01')),
       ((3, b'\x7f\x00\x00\x01'), (CertType.AUTHENTICATE, 3, b'\x7f\x00\x00\x01')),
-      ((4, b'\x7f\x00\x00\x01'), (CertType.UNKNOWN, 4, b'\x7f\x00\x00\x01')),
+      ((4, b'\x7f\x00\x00\x01'), (CertType.ED25519_SIGNING, 4, b'\x7f\x00\x00\x01')),
       ((CertType.IDENTITY, b'\x7f\x00\x00\x01'), (CertType.IDENTITY, 2, b'\x7f\x00\x00\x01')),
     )
 
diff --git a/test/unit/descriptor/certificate.py b/test/unit/descriptor/certificate.py
index 6d2fd378..26e091c1 100644
--- a/test/unit/descriptor/certificate.py
+++ b/test/unit/descriptor/certificate.py
@@ -12,7 +12,8 @@ import stem.util.str_tools
 import stem.prereq
 import test.require
 
-from stem.descriptor.certificate import ED25519_SIGNATURE_LENGTH, CertType, ExtensionType, ExtensionFlag, Ed25519Certificate, Ed25519CertificateV1, Ed25519Extension
+from stem.client.datatype import CertType
+from stem.descriptor.certificate import ED25519_SIGNATURE_LENGTH, ExtensionType, ExtensionFlag, Ed25519Certificate, Ed25519CertificateV1, Ed25519Extension
 from test.unit.descriptor import get_resource
 
 from cryptography.hazmat.primitives import serialization
@@ -61,7 +62,7 @@ class TestEd25519Certificate(unittest.TestCase):
     self.assertEqual(Ed25519CertificateV1, type(cert))
     self.assertEqual(1, cert.version)
     self.assertEqual(stem.util.str_tools._to_unicode(cert_bytes), cert.encoded)
-    self.assertEqual(CertType.SIGNING, cert.type)
+    self.assertEqual(CertType.ED25519_SIGNING, cert.type)
     self.assertEqual(datetime.datetime(1970, 1, 1, 0, 0), cert.expiration)
     self.assertEqual(1, cert.key_type)
     self.assertEqual(b'\x03' * 32, cert.key)
@@ -85,7 +86,7 @@ class TestEd25519Certificate(unittest.TestCase):
     self.assertEqual(Ed25519CertificateV1, type(cert))
     self.assertEqual(1, cert.version)
     self.assertEqual(ED25519_CERT, cert.encoded)
-    self.assertEqual(CertType.SIGNING, cert.type)
+    self.assertEqual(CertType.ED25519_SIGNING, cert.type)
     self.assertEqual(datetime.datetime(2015, 8, 28, 17, 0), cert.expiration)
     self.assertEqual(1, cert.key_type)
     self.assertEqual(EXPECTED_CERT_KEY, cert.key)
@@ -126,9 +127,12 @@ class TestEd25519Certificate(unittest.TestCase):
     are reserved.
     """
 
-    exc_msg = 'Ed25519 certificate cannot have a type of 0. This is reserved to avoid conflicts with tor CERTS cells.'
+    exc_msg = 'Ed25519 certificate type 0 is unrecognized'
     self.assertRaisesWith(ValueError, exc_msg, Ed25519Certificate.parse, certificate(cert_type = 0))
 
+    exc_msg = 'Ed25519 certificate cannot have a type of 1. This is reserved for CERTS cells.'
+    self.assertRaisesWith(ValueError, exc_msg, Ed25519Certificate.parse, certificate(cert_type = 1))
+
     exc_msg = 'Ed25519 certificate cannot have a type of 7. This is reserved for RSA identity cross-certification.'
     self.assertRaisesWith(ValueError, exc_msg, Ed25519Certificate.parse, certificate(cert_type = 7))
 
diff --git a/test/unit/descriptor/server_descriptor.py b/test/unit/descriptor/server_descriptor.py
index 6b91d90f..d87d51e9 100644
--- a/test/unit/descriptor/server_descriptor.py
+++ b/test/unit/descriptor/server_descriptor.py
@@ -20,8 +20,9 @@ import stem.version
 import stem.util.str_tools
 import test.require
 
+from stem.client.datatype import CertType
 from stem.descriptor import DigestHash, DigestEncoding
-from stem.descriptor.certificate import CertType, ExtensionType
+from stem.descriptor.certificate import ExtensionType
 from stem.descriptor.server_descriptor import BridgeDistribution, RelayDescriptor, BridgeDescriptor
 
 from test.unit.descriptor import (
@@ -366,7 +367,7 @@ Qlx9HNCqCY877ztFRC624ja2ql6A2hBcuoYMbkHjcQ4=
     ])
 
     self.assertEqual(1, desc.certificate.version)
-    self.assertEqual(CertType.SIGNING, desc.certificate.type)
+    self.assertEqual(CertType.ED25519_SIGNING, desc.certificate.type)
     self.assertEqual(datetime.datetime(2015, 8, 28, 17, 0, 0), desc.certificate.expiration)
     self.assertEqual(1, desc.certificate.key_type)
     self.assertTrue(desc.certificate.key.startswith(b'\xa5\xb6\x1a\x80D\x0f'))



_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits