Commit 67252eb7 authored by Damian Johnson's avatar Damian Johnson
Browse files

Migrate from pycrypto to cryptography module

Stem had an optional dependency on pycrypto to validate descriptor signatures
but seems the module is no longer maintained...

  https://github.com/dlitz/pycrypto/issues/173

Moving to the cryptography module (https://cryptography.io/en/latest/).

Thanks Patrick!
parents c5cef004 1551fc5e
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ The following are only available within Stem's `git repository

 * **Descriptors**

  * Moved from the deprecated `pycrypto <https://www.dlitz.net/software/pycrypto/>`_ module to `cryptography <https://pypi.python.org/pypi/cryptography>`_ for validating signatures (:trac:`21086`)
  * Sped descriptor reading by ~25% by deferring defaulting when validating
  * Support for protocol descriptor fields (:spec:`eb4fb3c`)
  * Shared randomness properties weren't being read in votes (:trac:`21102`)
+19 −3
Original line number Diff line number Diff line
@@ -52,11 +52,27 @@ Does Stem have any dependencies?

**No.** All you need in order to use Stem is Python.

When it is available Stem will use `pycrypto
<https://www.dlitz.net/software/pycrypto/>`_ to validate descriptor signatures.
However, there is no need to install pycrypto unless you need this
When it is available Stem will use `cryptography
<https://pypi.python.org/pypi/cryptography>`_ to validate descriptor signatures.
However, there is no need to install cryptography unless you need this
functionality.

Note that if cryptography installation fails with...

::

  build/temp.linux-i686-2.7/_openssl.c:18:20: fatal error: Python.h: No such file or directory
  compilation terminated.
  error: command 'gcc' failed with exit status 1

You need python-dev. For instance on Debian and Ubuntu you can install
cryptography with...

::

  % sudo apt-get install python-dev
  % sudo pip install cryptography

.. _what_python_versions_is_stem_compatible_with:

What Python versions is Stem compatible with?
+1 −1
Original line number Diff line number Diff line
mock
pyflakes
pycodestyle
pycrypto
tox
cryptography
+1 −1
Original line number Diff line number Diff line
@@ -160,7 +160,7 @@ def main():
    Task('checking stem version', test.util.check_stem_version),
    tor_version_check,
    Task('checking python version', test.util.check_python_version),
    Task('checking pycrypto version', test.util.check_pycrypto_version),
    Task('checking cryptography version', test.util.check_cryptography_version),
    Task('checking mock version', test.util.check_mock_version),
    Task('checking pyflakes version', test.util.check_pyflakes_version),
    Task('checking pycodestyle version', test.util.check_pycodestyle_version),
+9 −11
Original line number Diff line number Diff line
@@ -563,19 +563,18 @@ class Descriptor(object):
    """

    if not stem.prereq.is_crypto_available():
      raise ValueError('Generating the signed digest requires pycrypto')
      raise ValueError('Generating the signed digest requires the cryptography module')

    from Crypto.Util import asn1
    from Crypto.Util.number import bytes_to_long, long_to_bytes
    from cryptography.hazmat.backends import default_backend
    from cryptography.hazmat.primitives.serialization import load_der_public_key
    from cryptography.utils import int_to_bytes, int_from_bytes

    # get the ASN.1 sequence

    seq = asn1.DerSequence()
    seq.decode(_bytes_for_block(signing_key))
    modulus, public_exponent = seq[0], seq[1]
    key = load_der_public_key(_bytes_for_block(signing_key), default_backend())
    modulus = key.public_numbers().n
    public_exponent = key.public_numbers().e

    sig_as_bytes = _bytes_for_block(signature)
    sig_as_long = bytes_to_long(sig_as_bytes)  # convert signature to an int
    sig_as_long = int_from_bytes(sig_as_bytes, byteorder='big')  # convert signature to an int
    blocksize = 128  # block size will always be 128 for a 1024 bit key

    # use the public exponent[e] & the modulus[n] to decrypt the int
@@ -583,8 +582,7 @@ class Descriptor(object):
    decrypted_int = pow(sig_as_long, public_exponent, modulus)

    # convert the int to a byte array

    decrypted_bytes = long_to_bytes(decrypted_int, blocksize)
    decrypted_bytes = int_to_bytes(decrypted_int, blocksize)

    ############################################################################
    # The decrypted bytes should have a structure exactly along these lines.
Loading