commit 8129f9fa4f624b10ecdec4c47b0ec9e486597708 Author: Damian Johnson atagar@torproject.org Date: Mon Jun 19 15:10:10 2017 -0700
Merge 'generate' helpers into descriptor creation
On reflection these helpers aren't adding much right now. We might twiddle this more as we sign additional descriptor types but this approach lets the caller provide their own signing key. --- stem/descriptor/server_descriptor.py | 69 +++++++++++------------------------- 1 file changed, 21 insertions(+), 48 deletions(-)
diff --git a/stem/descriptor/server_descriptor.py b/stem/descriptor/server_descriptor.py index 8204c44..3ad019a 100644 --- a/stem/descriptor/server_descriptor.py +++ b/stem/descriptor/server_descriptor.py @@ -33,7 +33,6 @@ etc). This information is provided from a few sources...
import base64 import binascii -import collections import functools import hashlib import re @@ -74,8 +73,6 @@ try: except ImportError: from stem.util.lru_cache import lru_cache
-SigningKey = collections.namedtuple('SigningKey', ['public', 'private', 'descriptor_signing_key']) - # relay descriptors must have exactly one of the following REQUIRED_FIELDS = ( 'router', @@ -214,45 +211,6 @@ def _parse_file(descriptor_file, is_bridge = False, validate = False, **kwargs): break # done parsing descriptors
-def _generate_signing_key(): - """ - Creates a key that can be used to sign server descriptors. - """ - - from cryptography.hazmat.backends import default_backend - from cryptography.hazmat.primitives import serialization - from cryptography.hazmat.primitives.asymmetric import rsa - - private_key = rsa.generate_private_key( - public_exponent = 65537, - key_size = 1024, - backend = default_backend(), - ) - - public_key = private_key.public_key() - - pem = public_key.public_bytes( - encoding = serialization.Encoding.PEM, - format = serialization.PublicFormat.PKCS1, - ).strip() - - return SigningKey(public_key, private_key, pem) - - -def _generate_signature(content, signing_key): - """ - Creates the 'router-signature' signature block (excluding the - 'router-signature\n' prefix since that should be part of the - signed content). - """ - - from cryptography.hazmat.primitives import hashes - from cryptography.hazmat.primitives.asymmetric import padding - - signature = base64.b64encode(signing_key.private.sign(content, padding.PKCS1v15(), hashes.SHA1())) - return '-----BEGIN SIGNATURE-----\n' + '\n'.join(stem.util.str_tools._split_by_length(signature, 64)) + '\n-----END SIGNATURE-----\n' - - def _parse_router_line(descriptor, entries): # "router" nickname address ORPort SocksPort DirPort
@@ -859,7 +817,7 @@ class RelayDescriptor(ServerDescriptor): self.certificate.validate(self)
@classmethod - def content(cls, attr = None, exclude = (), sign = False): + def content(cls, attr = None, exclude = (), sign = False, private_signing_key = None): if sign: if not stem.prereq.is_crypto_available(): raise ImportError('Signing requires the cryptography module') @@ -868,23 +826,38 @@ class RelayDescriptor(ServerDescriptor): elif attr and 'router-signature' in attr: raise ValueError('Cannot sign the descriptor if a router-signature has been provided')
+ from cryptography.hazmat.backends import default_backend + from cryptography.hazmat.primitives import hashes, serialization + from cryptography.hazmat.primitives.asymmetric import padding, rsa + if attr is None: attr = {}
+ if private_signing_key is None: + private_signing_key = rsa.generate_private_key( + public_exponent = 65537, + key_size = 1024, + backend = default_backend(), + ) + # create descriptor content without the router-signature, then # appending the content signature
- signing_key = _generate_signing_key() - attr['signing-key'] = '\n' + signing_key.descriptor_signing_key + attr['signing-key'] = '\n' + private_signing_key.public_key().public_bytes( + encoding = serialization.Encoding.PEM, + format = serialization.PublicFormat.PKCS1, + ).strip() + content = _descriptor_content(attr, exclude, sign, RELAY_SERVER_HEADER) + '\nrouter-signature\n' + signature = base64.b64encode(private_signing_key.sign(content, padding.PKCS1v15(), hashes.SHA1()))
- return content + _generate_signature(content, signing_key) + return content + '\n'.join(['-----BEGIN SIGNATURE-----'] + stem.util.str_tools._split_by_length(signature, 64) + ['-----END SIGNATURE-----\n']) else: return _descriptor_content(attr, exclude, sign, RELAY_SERVER_HEADER, RELAY_SERVER_FOOTER)
@classmethod - def create(cls, attr = None, exclude = (), validate = True, sign = False): - return cls(cls.content(attr, exclude, sign), validate = validate, skip_crypto_validation = not sign) + def create(cls, attr = None, exclude = (), validate = True, sign = False, private_signing_key = None): + return cls(cls.content(attr, exclude, sign, private_signing_key), validate = validate, skip_crypto_validation = not sign)
@lru_cache() def digest(self):
tor-commits@lists.torproject.org