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

[tor-commits] [stem/master] Implement certificate encoding



commit 0d726d07e7d8cf0226d2b5a74c24b6f9181493a4
Author: Damian Johnson <atagar@xxxxxxxxxxxxxx>
Date:   Wed Oct 23 16:28:35 2019 -0700

    Implement certificate encoding
    
    There we go. Now that we parse certificates and extensions like datatypes we
    can implement their packing methods.
---
 stem/descriptor/certificate.py      | 23 +++++++++++++++++++++++
 test/unit/descriptor/certificate.py | 26 +++++++++++++++++++++++++-
 2 files changed, 48 insertions(+), 1 deletion(-)

diff --git a/stem/descriptor/certificate.py b/stem/descriptor/certificate.py
index dcf0c227..855f1262 100644
--- a/stem/descriptor/certificate.py
+++ b/stem/descriptor/certificate.py
@@ -79,6 +79,7 @@ import re
 import stem.descriptor.hidden_service
 import stem.descriptor.server_descriptor
 import stem.prereq
+import stem.util
 import stem.util.enum
 import stem.util.str_tools
 
@@ -132,6 +133,14 @@ class Ed25519Extension(Field):
     if ext_type == ExtensionType.HAS_SIGNING_KEY and len(data) != 32:
       raise ValueError('Ed25519 HAS_SIGNING_KEY extension must be 32 bytes, but was %i.' % len(data))
 
+  def pack(self):
+    encoded = bytearray()
+    encoded += Size.SHORT.pack(len(self.data))
+    encoded += Size.CHAR.pack(self.type)
+    encoded += Size.CHAR.pack(self.flag_int)
+    encoded += self.data
+    return bytes(encoded)
+
   @staticmethod
   def pop(content):
     if len(content) < 4:
@@ -265,6 +274,20 @@ class Ed25519CertificateV1(Ed25519Certificate):
       raise ValueError('Ed25519 certificate type %i is unrecognized' % self.type_int)
 
   def to_base64(self, pem = False):
+    if self.encoded is None:
+      encoded = bytearray()
+      encoded += Size.CHAR.pack(self.version)
+      encoded += Size.CHAR.pack(self.type_int)
+      encoded += Size.LONG.pack(stem.util.datetime_to_unix(self.expiration) / 3600)
+      encoded += Size.CHAR.pack(self.key_type)
+      encoded += self.key
+      encoded += Size.CHAR.pack(len(self.extensions))
+
+      for extension in self.extensions:
+        encoded += extension.pack()
+
+      self.encoded = '\n'.join(stem.util.str_tools._split_by_length(base64.b64encode(bytes(encoded + self.signature)), 64))
+
     if pem:
       return '-----BEGIN ED25519 CERT-----\n%s\n-----END ED25519 CERT-----' % self.encoded
     else:
diff --git a/test/unit/descriptor/certificate.py b/test/unit/descriptor/certificate.py
index dc7ff184..a5f7837a 100644
--- a/test/unit/descriptor/certificate.py
+++ b/test/unit/descriptor/certificate.py
@@ -12,7 +12,7 @@ import stem.util.str_tools
 import stem.prereq
 import test.require
 
-from stem.client.datatype import CertType
+from stem.client.datatype import Size, CertType
 from stem.descriptor.certificate import ED25519_SIGNATURE_LENGTH, ExtensionType, Ed25519Certificate, Ed25519CertificateV1, Ed25519Extension
 from test.unit.descriptor import get_resource
 
@@ -93,6 +93,30 @@ class TestEd25519Certificate(unittest.TestCase):
     self.assertEqual([Ed25519Extension(4, 0, EXPECTED_EXTENSION_DATA)], cert.extensions)
     self.assertEqual(EXPECTED_SIGNATURE, cert.signature)
 
+  def test_extension_encoding(self):
+    """
+    Pack an extension back into what we read.
+    """
+
+    extension = Ed25519Certificate.from_base64(ED25519_CERT).extensions[0]
+    expected = Size.SHORT.pack(len(EXPECTED_EXTENSION_DATA)) + Size.CHAR.pack(4) + Size.CHAR.pack(0) + EXPECTED_EXTENSION_DATA
+
+    self.assertEqual(4, extension.type)
+    self.assertEqual(0, extension.flag_int)
+    self.assertEqual(EXPECTED_EXTENSION_DATA, extension.data)
+    self.assertEqual(expected, extension.pack())
+
+  def test_certificate_encoding(self):
+    """
+    Pack a certificate back into what we read.
+    """
+
+    cert = Ed25519Certificate.from_base64(ED25519_CERT)
+    self.assertEqual(ED25519_CERT, cert.encoded)
+
+    cert.encoded = None  # clear cached encoding
+    self.assertEqual(ED25519_CERT, cert.to_base64())
+
   def test_non_base64(self):
     """
     Parse data that isn't base64 encoded.



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